diff --git a/.github/workflows/codeql.yml b/.github/workflows/codeql.yml
index 1e371505c..4d2a3479d 100644
--- a/.github/workflows/codeql.yml
+++ b/.github/workflows/codeql.yml
@@ -35,12 +35,12 @@ jobs:
python -m pip install --no-cache-dir --require-hashes -r src/common/db/requirements.txt
echo "CODEQL_PYTHON=$(which python)" >> $GITHUB_ENV
- name: Initialize CodeQL
- uses: github/codeql-action/init@e5f05b81d5b6ff8cfa111c80c22c5fd02a384118 # v3.23.0
+ uses: github/codeql-action/init@0b21cf2492b6b02c465a3e5d7c473717ad7721ba # v3.23.1
with:
languages: ${{ matrix.language }}
config-file: ./.github/codeql.yml
setup-python-dependencies: false
- name: Perform CodeQL Analysis
- uses: github/codeql-action/analyze@e5f05b81d5b6ff8cfa111c80c22c5fd02a384118 # v3.23.0
+ uses: github/codeql-action/analyze@0b21cf2492b6b02c465a3e5d7c473717ad7721ba # v3.23.1
with:
category: "/language:${{matrix.language}}"
diff --git a/.github/workflows/container-build.yml b/.github/workflows/container-build.yml
index 85adacf3c..5747a11bf 100644
--- a/.github/workflows/container-build.yml
+++ b/.github/workflows/container-build.yml
@@ -56,6 +56,8 @@ jobs:
echo "$SSH_KEY" > ~/.ssh/id_rsa_arm
chmod 600 ~/.ssh/id_rsa_arm
echo "$SSH_CONFIG" | sed "s/SSH_IP/$SSH_IP/g" > ~/.ssh/config
+ echo "ServerAliveInterval 60" >> ~/.ssh/config
+ echo "ServerAliveCountMax 10" >> ~/.ssh/config
env:
SSH_KEY: ${{ secrets.ARM_SSH_KEY }}
SSH_IP: ${{ secrets.ARM_SSH_IP }}
diff --git a/.github/workflows/create-arm.yml b/.github/workflows/create-arm.yml
index e1f272c48..9bb50ff84 100644
--- a/.github/workflows/create-arm.yml
+++ b/.github/workflows/create-arm.yml
@@ -46,7 +46,7 @@ jobs:
default-organization-id: ${{ secrets.SCW_DEFAULT_ORGANIZATION_ID }}
- name: Extract ARM type
run: |
- TYPE=$(echo "$JSON" | jq '.servers | with_entries(select(.key | contains("AMP"))) | with_entries(select(.value.availability != "shortage")) | keys[] | select(. | test("^AMP2-C[0-9]+$")) | sub("AMP2-C"; "") | tonumber' | sort -n | tail -n 1 | xargs -I {} echo "AMP2-C{}")
+ TYPE=$(echo "$JSON" | jq '.servers | with_entries(select(.key | contains("COPARM1-"))) | with_entries(select(.value.availability != "shortage")) | keys[] | select(. | test("^COPARM1-[0-9]+C-[0-9]+G$"))' | sed 's/"//g' | cut -d '-' -f 2,3 | sort -g | tail -n 1 | xargs -I {} echo "COPARM1-{}")
echo "Type is $TYPE"
echo "TYPE=$TYPE" >> "$GITHUB_ENV"
env:
@@ -81,6 +81,6 @@ jobs:
SSH_IP: ${{ fromJson(steps.scw.outputs.json).public_ip.address }}
SSH_CONFIG: ${{ secrets.ARM_SSH_CONFIG }}
- name: Install Docker
- run: ssh root@$SSH_IP "curl -fsSL https://test.docker.com -o test-docker.sh ; sh test-docker.sh"
+ run: ssh root@$SSH_IP "curl -fsSL https://test.docker.com -o test-docker.sh ; sh test-docker.sh ; echo 'ClientAliveInterval 60' >> /etc/ssh/sshd_config ; echo 'ClientAliveCountMax 0' >> /etc/ssh/sshd_config ; systemctl restart ssh"
env:
SSH_IP: ${{ fromJson(steps.scw.outputs.json).public_ip.address }}
diff --git a/.github/workflows/dev.yml b/.github/workflows/dev.yml
index f5df172ac..adf4045b3 100644
--- a/.github/workflows/dev.yml
+++ b/.github/workflows/dev.yml
@@ -13,6 +13,7 @@ jobs:
contents: read
packages: write
strategy:
+ fail-fast: false
matrix:
image: [bunkerweb, scheduler, autoconf, ui]
include:
@@ -84,7 +85,6 @@ jobs:
# Core tests
prepare-tests-core:
- needs: [build-containers, build-packages]
runs-on: ubuntu-latest
steps:
- name: Checkout repository
@@ -96,7 +96,7 @@ jobs:
outputs:
tests: ${{ steps.set-matrix.outputs.tests }}
tests-core:
- needs: prepare-tests-core
+ needs: [build-containers, prepare-tests-core]
strategy:
fail-fast: false
matrix:
@@ -106,7 +106,7 @@ jobs:
TEST: ${{ matrix.test }}
RELEASE: dev
tests-core-linux:
- needs: prepare-tests-core
+ needs: [build-packages, prepare-tests-core]
strategy:
fail-fast: false
matrix:
diff --git a/.github/workflows/doc-to-pdf.yml b/.github/workflows/doc-to-pdf.yml
index f840d2ba2..ae5aac03a 100644
--- a/.github/workflows/doc-to-pdf.yml
+++ b/.github/workflows/doc-to-pdf.yml
@@ -18,8 +18,8 @@ jobs:
uses: actions/setup-python@0a5c61591373683505ea898e09a3ea4f39ef2b9c # v5.0.0
with:
python-version: "3.10"
- - name: Install doc requirements
- run: pip install --no-cache-dir --require-hashes -r docs/requirements.txt
+ - name: Install doc dependencies
+ run: pip install --no-cache-dir --require-hashes -r docs/requirements.txt && sudo apt install -y libcairo2-dev libfreetype6-dev libffi-dev libjpeg-dev libpng-dev libz-dev
- name: Install chromium
run: sudo apt install chromium-browser
- name: Install node
@@ -32,7 +32,7 @@ jobs:
run: mkdocs serve & sleep 10
- name: Run pdf script
run: node docs/misc/pdf.js http://localhost:8000/print_page/ BunkerWeb_documentation_v${{ inputs.VERSION }}.pdf 'BunkerWeb documentation v${{ inputs.VERSION }}'
- - uses: actions/upload-artifact@c7d193f32edcb7bfad88892161225aeda64e9392 # v4.0.0
+ - uses: actions/upload-artifact@694cdabd8bdb0f10b2cea11669e1bf5453eed0a6 # v4.2.0
with:
name: BunkerWeb_documentation_v${{ inputs.VERSION }}.pdf
path: BunkerWeb_documentation_v${{ inputs.VERSION }}.pdf
diff --git a/.github/workflows/linux-build.yml b/.github/workflows/linux-build.yml
index ad70387e2..71c26d77f 100644
--- a/.github/workflows/linux-build.yml
+++ b/.github/workflows/linux-build.yml
@@ -65,6 +65,8 @@ jobs:
echo "$SSH_KEY" > ~/.ssh/id_rsa_arm
chmod 600 ~/.ssh/id_rsa_arm
echo "$SSH_CONFIG" | sed "s/SSH_IP/$SSH_IP/g" > ~/.ssh/config
+ echo "ServerAliveInterval 60" >> ~/.ssh/config
+ echo "ServerAliveCountMax 10" >> ~/.ssh/config
env:
SSH_KEY: ${{ secrets.ARM_SSH_KEY }}
SSH_IP: ${{ secrets.ARM_SSH_IP }}
@@ -127,7 +129,7 @@ jobs:
scp -r root@arm:/root/package-${{ inputs.LINUX }} ./package-${{ inputs.LINUX }}
env:
LARCH: ${{ env.LARCH }}
- - uses: actions/upload-artifact@c7d193f32edcb7bfad88892161225aeda64e9392 # v4.0.0
+ - uses: actions/upload-artifact@694cdabd8bdb0f10b2cea11669e1bf5453eed0a6 # v4.2.0
with:
name: package-${{ inputs.LINUX }}-${{ env.LARCH }}
path: package-${{ inputs.LINUX }}/*.${{ inputs.PACKAGE }}
diff --git a/.github/workflows/push-doc.yml b/.github/workflows/push-doc.yml
index 6f7fbc317..319a11d3e 100644
--- a/.github/workflows/push-doc.yml
+++ b/.github/workflows/push-doc.yml
@@ -32,8 +32,8 @@ jobs:
- uses: actions/setup-python@0a5c61591373683505ea898e09a3ea4f39ef2b9c # v5.0.0
with:
python-version: "3.10"
- - name: Install doc requirements
- run: pip install --no-cache-dir --require-hashes -r docs/requirements.txt
+ - name: Install doc dependencies
+ run: pip install --no-cache-dir --require-hashes -r docs/requirements.txt && sudo apt install -y libcairo2-dev libfreetype6-dev libffi-dev libjpeg-dev libpng-dev libz-dev
- name: Push doc
run: mike deploy --update-aliases --push --alias-type=copy ${{ inputs.VERSION }} ${{ inputs.ALIAS }}
- name: Set default doc
diff --git a/.github/workflows/push-docker.yml b/.github/workflows/push-docker.yml
index 5a5ab655c..ee576a2b7 100644
--- a/.github/workflows/push-docker.yml
+++ b/.github/workflows/push-docker.yml
@@ -51,6 +51,8 @@ jobs:
echo "$SSH_KEY" > ~/.ssh/id_rsa_arm
chmod 600 ~/.ssh/id_rsa_arm
echo "$SSH_CONFIG" | sed "s/SSH_IP/$SSH_IP/g" > ~/.ssh/config
+ echo "ServerAliveInterval 60" >> ~/.ssh/config
+ echo "ServerAliveCountMax 10" >> ~/.ssh/config
env:
SSH_KEY: ${{ secrets.ARM_SSH_KEY }}
SSH_IP: ${{ secrets.ARM_SSH_IP }}
diff --git a/.github/workflows/push-packagecloud.yml b/.github/workflows/push-packagecloud.yml
index 216e3c726..2a2113256 100644
--- a/.github/workflows/push-packagecloud.yml
+++ b/.github/workflows/push-packagecloud.yml
@@ -42,7 +42,7 @@ jobs:
- name: Check out repository code
uses: actions/checkout@b4ffde65f46336ab88eb53be808477a3936bae11 # v4.1.1
- name: Install ruby
- uses: ruby/setup-ruby@360dc864d5da99d54fcb8e9148c14a84b90d3e88 # v1.165.1
+ uses: ruby/setup-ruby@5daca165445f0ae10478593083f72ca2625e241d # v1.169.0
with:
ruby-version: "3.0"
- name: Install packagecloud
diff --git a/.github/workflows/scorecards-analysis.yml b/.github/workflows/scorecards-analysis.yml
index c4be7af18..1bcdc5320 100644
--- a/.github/workflows/scorecards-analysis.yml
+++ b/.github/workflows/scorecards-analysis.yml
@@ -25,6 +25,6 @@ jobs:
results_format: sarif
publish_results: true
- name: "Upload SARIF results to code scanning"
- uses: github/codeql-action/upload-sarif@e5f05b81d5b6ff8cfa111c80c22c5fd02a384118 # v3.23.0
+ uses: github/codeql-action/upload-sarif@0b21cf2492b6b02c465a3e5d7c473717ad7721ba # v3.23.1
with:
sarif_file: results.sarif
diff --git a/.github/workflows/staging-create-infra.yml b/.github/workflows/staging-create-infra.yml
index e6e121285..fac4f3087 100644
--- a/.github/workflows/staging-create-infra.yml
+++ b/.github/workflows/staging-create-infra.yml
@@ -55,7 +55,7 @@ jobs:
if: always()
env:
SECRET_KEY: ${{ secrets.SECRET_KEY }}
- - uses: actions/upload-artifact@c7d193f32edcb7bfad88892161225aeda64e9392 # v4.0.0
+ - uses: actions/upload-artifact@694cdabd8bdb0f10b2cea11669e1bf5453eed0a6 # v4.2.0
if: always()
with:
name: tf-${{ inputs.TYPE }}
diff --git a/.github/workflows/staging.yml b/.github/workflows/staging.yml
index 8b04007f0..a00d03d0c 100644
--- a/.github/workflows/staging.yml
+++ b/.github/workflows/staging.yml
@@ -85,7 +85,6 @@ jobs:
SECRET_KEY: ${{ secrets.SECRET_KEY }}
K8S_IP: ${{ secrets.K8S_IP }}
prepare-tests-core:
- needs: [codeql, build-containers, build-packages]
runs-on: ubuntu-latest
steps:
- name: Checkout repository
@@ -130,7 +129,7 @@ jobs:
RUNS_ON: ${{ matrix.runs_on }}
secrets: inherit
tests-core:
- needs: prepare-tests-core
+ needs: [build-containers, prepare-tests-core]
strategy:
fail-fast: false
matrix:
@@ -140,7 +139,7 @@ jobs:
TEST: ${{ matrix.test }}
RELEASE: testing
tests-core-linux:
- needs: prepare-tests-core
+ needs: [build-packages, prepare-tests-core]
strategy:
fail-fast: false
matrix:
diff --git a/.github/workflows/test-core-linux.yml b/.github/workflows/test-core-linux.yml
index a8c190d6f..2a619c7f5 100644
--- a/.github/workflows/test-core-linux.yml
+++ b/.github/workflows/test-core-linux.yml
@@ -97,7 +97,7 @@ jobs:
run: |
export MAKEFLAGS="-j $(nproc)"
pip install --no-cache-dir --ignore-installed --require-hashes -r src/deps/requirements-deps.txt
- MAKEFLAGS="-j $(nproc)" find tests/core -name "requirements.txt" -exec pip install --no-cache-dir --require-hashes --no-deps -r {} \;
- cd ./tests/core/${{ inputs.TEST }}
+ cd tests/core/${{ inputs.TEST }}
+ find . -name "requirements.txt" -exec pip install --no-cache-dir --require-hashes --no-deps -r {} \;
sudo truncate -s 0 /var/log/bunkerweb/error.log
./test.sh "linux"
diff --git a/.github/workflows/tests-ui-linux.yml b/.github/workflows/tests-ui-linux.yml
index 8b59645d4..bf9ae398d 100644
--- a/.github/workflows/tests-ui-linux.yml
+++ b/.github/workflows/tests-ui-linux.yml
@@ -66,14 +66,13 @@ jobs:
- name: Fix version without a starting number
if: inputs.RELEASE == 'testing' || inputs.RELEASE == 'dev' || inputs.RELEASE == 'ui'
run: echo "force-bad-version" | sudo tee -a /etc/dpkg/dpkg.cfg
- - name: Install BunkerWeb
- run: sudo apt install -fy /tmp/bunkerweb.deb
- name: Edit configuration files
run: |
# Misc
echo "127.0.0.1 www.example.com" | sudo tee -a /etc/hosts
echo "127.0.0.1 app1.example.com" | sudo tee -a /etc/hosts
# BunkerWeb
+ sudo mkdir -p /etc/bunkerweb
echo "SERVER_NAME=" | sudo tee /etc/bunkerweb/variables.env
echo "HTTP_PORT=80" | sudo tee -a /etc/bunkerweb/variables.env
echo 'DNS_RESOLVERS=9.9.9.9 8.8.8.8 8.8.4.4' | sudo tee -a /etc/bunkerweb/variables.env
@@ -92,6 +91,8 @@ jobs:
sudo chown nginx:nginx /etc/bunkerweb/variables.env /etc/bunkerweb/ui.env
sudo chmod 777 /etc/bunkerweb/variables.env /etc/bunkerweb/ui.env
+ - name: Install BunkerWeb
+ run: sudo apt install -fy /tmp/bunkerweb.deb
- name: Run tests
run: |
export MAKEFLAGS="-j $(nproc)"
diff --git a/.pre-commit-config.yaml b/.pre-commit-config.yaml
index baee1ba60..8ae7f6c38 100644
--- a/.pre-commit-config.yaml
+++ b/.pre-commit-config.yaml
@@ -1,6 +1,6 @@
# See https://pre-commit.com for more information
# See https://pre-commit.com/hooks.html for more hooks
-exclude: (^LICENSE.md$|^src/VERSION$|^env/|^src/(bw/misc/root-ca.pem$|deps/src/|common/core/modsecurity/files|ui/static/js/(editor/|utils/purify/|tsparticles\.bundle\.min\.js))|\.(svg|drawio|patch\d?|ascii|tf|tftpl|key)$)
+exclude: (^LICENSE.md$|^src/VERSION$|^env/|^src/(bw/misc/root-ca.pem$|deps/src/|common/core/modsecurity/files|ui/static/(js/(editor/|utils/purify/|tsparticles\.bundle\.min\.js)|css/dashboard\.css))|\.(svg|drawio|patch\d?|ascii|tf|tftpl|key)$)
repos:
- repo: https://github.com/pre-commit/pre-commit-hooks
rev: c4a0b883114b00d8d76b479c820ce7950211c99b # frozen: v4.5.0
@@ -30,7 +30,7 @@ repos:
name: Prettier Code Formatter
- repo: https://github.com/JohnnyMorganz/StyLua
- rev: f9afc7f33bc19f7708fbc1d7eea0606e0d41080a # frozen: v0.19.1
+ rev: 84c370104d6a8d1eef00c80a3ebd42f7033aaaad # frozen: v0.20.0
hooks:
- id: stylua-github
exclude: ^src/(bw/lua/middleclass.lua|common/core/antibot/captcha.lua)$
@@ -50,7 +50,7 @@ repos:
args: ["--max-line-length=250", "--ignore=E266,E402,E722,W503"]
- repo: https://github.com/dosisod/refurb
- rev: a7c461fcfaa2ca3248d489cdf7fed8e2d4fd8520 # frozen: v1.26.0
+ rev: a295cee6d188f5797aefe5d7cf77a353ed48ea93 # frozen: v1.27.0
hooks:
- id: refurb
name: Refurb Python Refactoring Tool
@@ -62,7 +62,7 @@ repos:
- id: codespell
name: Codespell Spell Checker
exclude: (^src/(ui/templates|common/core/.+/files|bw/loading)/.+.html|modsecurity-rules.conf.*)$
- entry: codespell --ignore-regex="(tabEl|Widgits)" --skip src/ui/static/js/utils/flatpickr.js,CHANGELOG.md
+ entry: codespell --ignore-regex="(tabEl|Widgits)" --skip src/ui/static/js/utils/flatpickr.js,src/ui/static/css/style.css,CHANGELOG.md
language: python
types: [text]
diff --git a/.trivyignore b/.trivyignore
index e69de29bb..db367b1cd 100644
--- a/.trivyignore
+++ b/.trivyignore
@@ -0,0 +1 @@
+CVE-2023-6129
diff --git a/CHANGELOG.md b/CHANGELOG.md
index 115951f9e..f3729cea1 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -7,6 +7,7 @@
- [DEPS] Updated lua-nginx-module version to v0.10.26
- [DEPS] Updated libmaxminddb version to v1.9.1
- [DEPS] Updated lua-resty-core to v0.1.28
+- [DEPS] Updated zlib version to v1.3.1
## v1.5.5 - 2024/01/12
diff --git a/README.md b/README.md
index 714bbff8b..bb5462235 100644
--- a/README.md
+++ b/README.md
@@ -1,5 +1,5 @@
-
+
@@ -170,6 +170,10 @@ Another core component of BunkerWeb is the ModSecurity Web Application Firewall
## Database
+
+
+
+
State of the current configuration of BunkerWeb is stored in a backend database which contains the following data :
- Settings defined for all the services
diff --git a/docs/assets/img/bunkerweb_db.svg b/docs/assets/img/bunkerweb_db.svg
index d7f898638..4ef50e01e 100644
--- a/docs/assets/img/bunkerweb_db.svg
+++ b/docs/assets/img/bunkerweb_db.svg
@@ -1 +1,12 @@
-1 * * 1 1 * 1 * 1 * 1 * 1 * * 1 * 1 1 * bw_selects setting_id varchar[256] value varchar[256] bw_settings id varchar[256] name varchar[256] plugin_id varchar[64] context contexes default varchar[4096] help varchar[512] label varchar[256] regex varchar[1024] type settings_types multiple varchar[128] bw_services_settings service_id varchar[64] setting_id varchar[256] value varchar[4096] suffix int method methods bw_services id varchar[64] method methods bw_global_values setting_id varchar[256] value varchar[4096] suffix int method methods bw_plugins id varchar[64] name varchar[128] description varchar[256] version varchar[32] stream varchar[16] external boolean method methods data longblob checksum varchar[128] bw_jobs name varchar[128] plugin_id varchar[64] file_name varchar[256] every schedules reload boolean success boolean last_run datetime bw_jobs_cache id int job_name varchar[128] service_id varchar[64] file_name varchar[256] data longblob last_update datetime checksum varchar[128] bw_instances hostname varchar[256] port int server_name varchar[256] bw_metadata id int is_initialized boolean first_config_saved boolean autoconf_loaded boolean scheduler_first_start boolean custom_configs_changed boolean external_plugins_changed boolean config_changed boolean integration integrations version varchar bw_plugin_pages id int plugin_id varchar[64] template_file longblob template_checksum varchar[128] actions_file longblob actions_checksum varchar[128] bw_custom_configs id int service_id varchar[64] type custom_config_types name varchar[256] data longblob checksum varchar[128] method methods
\ No newline at end of file
+* 1 1 * 1 * * 1 * 1 1 * * 1 1 * 1 * * 1 bw_instances hostname varchar[256] port int server_name varchar[256] bw_services id varchar[64] method methods bw_global_values setting_id varchar[256] value varchar[8192] suffix int method methods bw_plugin_pages id int plugin_id varchar[64] template_file longblob template_checksum varchar[128] actions_file longblob actions_checksum varchar[128] bw_custom_configs id int service_id varchar[64] type custom_config_types name varchar[256] data longblob checksum varchar[128] method methods bw_services_settings service_id varchar[64] setting_id varchar[256] value varchar[8192] suffix int method methods bw_settings id varchar[256] name varchar[256] plugin_id varchar[64] context contexes default varchar[4096] help varchar[512] label varchar[256] regex varchar[1024] type settings_types multiple varchar[128] bw_selects setting_id varchar[256] value varchar[256] bw_ui_users id int username varchar[256] password varchar[60] is_two_factor_enabled boolean secret_token varchar[32] method methods bw_jobs_cache id int job_name varchar[128] service_id varchar[64] file_name varchar[256] data longblob last_update datetime checksum varchar[128] bw_jobs name varchar[128] plugin_id varchar[64] file_name varchar[256] every schedules reload boolean success boolean last_run datetime bw_plugins id varchar[64] name varchar[128] description varchar[256] version varchar[32] stream varchar[16] external boolean method methods data longblob checksum varchar[128] bw_metadata id int is_initialized boolean first_config_saved boolean autoconf_loaded boolean scheduler_first_start boolean custom_configs_changed boolean external_plugins_changed boolean config_changed boolean instances_changed boolean integration integrations version varchar
\ No newline at end of file
diff --git a/docs/package.json b/docs/package.json
new file mode 100644
index 000000000..176dbcd87
--- /dev/null
+++ b/docs/package.json
@@ -0,0 +1,5 @@
+{
+ "dependencies": {
+ "puppeteer": "^21.3.6"
+ }
+}
diff --git a/docs/quickstart-guide.md b/docs/quickstart-guide.md
index f98cbbf29..973b0d755 100644
--- a/docs/quickstart-guide.md
+++ b/docs/quickstart-guide.md
@@ -1,10 +1,12 @@
# Quickstart guide
!!! info "Prerequisites"
+
We assume that you're already familiar with the [core concepts](concepts.md) and you have followed the [integrations instructions](integrations.md) for your environment.
!!! tip "Going further"
- To demonstrate the use of BunkerWeb, we will deploy a dummy "Hello World" web application as an example. See the [examples folder](https://github.com/bunkerity/bunkerweb/tree/v1.5.5/examples) of the repository to get real-world examples.
+
+ To demonstrate the use of BunkerWeb, we will deploy a dummy "Hello World" web application as an example. See the [examples folder](https://github.com/bunkerity/bunkerweb/tree/v1.5.5/examples) of the repository to get real-world examples.
## Protect HTTP applications
@@ -1117,7 +1119,8 @@ REAL_IP_HEADER=proxy_protocol
## Protect UDP/TCP applications
!!! warning "Feature is in beta"
- This feature is not production-ready. Feel free to test it and report us any bug using [issues](https://github.com/bunkerity/bunkerweb/issues) in the GitHub repository.
+
+ This feature is not production-ready. Feel free to test it and report us any bug using [issues](https://github.com/bunkerity/bunkerweb/issues) in the GitHub repository.
BunkerWeb offers the capability to function as a **generic UDP/TCP reverse proxy**, allowing you to protect any network-based applications operating at least on layer 4 of the OSI model. Instead of utilizing the "classical" HTTP module, BunkerWeb leverages the [stream module](https://nginx.org/en/docs/stream/ngx_stream_core_module.html) of NGINX.
@@ -2329,7 +2332,8 @@ BunkerWeb supports PHP using external or remote [PHP-FPM](https://www.php.net/ma
## IPv6
!!! warning "Feature is in beta"
- This feature is not production-ready. Feel free to test it and report us any bug using [issues](https://github.com/bunkerity/bunkerweb/issues) in the GitHub repository.
+
+ This feature is not production-ready. Feel free to test it and report us any bug using [issues](https://github.com/bunkerity/bunkerweb/issues) in the GitHub repository.
By default, BunkerWeb will only listen on IPv4 addresses and won't use IPv6 for network communications. If you want to enable IPv6 support, you need to set `USE_IPV6=yes`. Please note that IPv6 configuration of your network and environment is out-of-the-scope of this documentation.
diff --git a/docs/requirements.in b/docs/requirements.in
index 6c4eeadba..232e85712 100644
--- a/docs/requirements.in
+++ b/docs/requirements.in
@@ -1,5 +1,5 @@
mike==2.0.0
mkdocs==1.5.3
-mkdocs-material[imaging]==9.5.3
+mkdocs-material[imaging]==9.5.4
mkdocs-print-site-plugin==2.3.6
pytablewriter==1.2.0
diff --git a/docs/requirements.txt b/docs/requirements.txt
index 29bf34752..8c12ad156 100644
--- a/docs/requirements.txt
+++ b/docs/requirements.txt
@@ -225,67 +225,67 @@ markdown==3.5.2 \
# mkdocs
# mkdocs-material
# pymdown-extensions
-markupsafe==2.1.3 \
- --hash=sha256:05fb21170423db021895e1ea1e1f3ab3adb85d1c2333cbc2310f2a26bc77272e \
- --hash=sha256:0a4e4a1aff6c7ac4cd55792abf96c915634c2b97e3cc1c7129578aa68ebd754e \
- --hash=sha256:10bbfe99883db80bdbaff2dcf681dfc6533a614f700da1287707e8a5d78a8431 \
- --hash=sha256:134da1eca9ec0ae528110ccc9e48041e0828d79f24121a1a146161103c76e686 \
- --hash=sha256:14ff806850827afd6b07a5f32bd917fb7f45b046ba40c57abdb636674a8b559c \
- --hash=sha256:1577735524cdad32f9f694208aa75e422adba74f1baee7551620e43a3141f559 \
- --hash=sha256:1b40069d487e7edb2676d3fbdb2b0829ffa2cd63a2ec26c4938b2d34391b4ecc \
- --hash=sha256:1b8dd8c3fd14349433c79fa8abeb573a55fc0fdd769133baac1f5e07abf54aeb \
- --hash=sha256:1f67c7038d560d92149c060157d623c542173016c4babc0c1913cca0564b9939 \
- --hash=sha256:282c2cb35b5b673bbcadb33a585408104df04f14b2d9b01d4c345a3b92861c2c \
- --hash=sha256:2c1b19b3aaacc6e57b7e25710ff571c24d6c3613a45e905b1fde04d691b98ee0 \
- --hash=sha256:2ef12179d3a291be237280175b542c07a36e7f60718296278d8593d21ca937d4 \
- --hash=sha256:338ae27d6b8745585f87218a3f23f1512dbf52c26c28e322dbe54bcede54ccb9 \
- --hash=sha256:3c0fae6c3be832a0a0473ac912810b2877c8cb9d76ca48de1ed31e1c68386575 \
- --hash=sha256:3fd4abcb888d15a94f32b75d8fd18ee162ca0c064f35b11134be77050296d6ba \
- --hash=sha256:42de32b22b6b804f42c5d98be4f7e5e977ecdd9ee9b660fda1a3edf03b11792d \
- --hash=sha256:47d4f1c5f80fc62fdd7777d0d40a2e9dda0a05883ab11374334f6c4de38adffd \
- --hash=sha256:504b320cd4b7eff6f968eddf81127112db685e81f7e36e75f9f84f0df46041c3 \
- --hash=sha256:525808b8019e36eb524b8c68acdd63a37e75714eac50e988180b169d64480a00 \
- --hash=sha256:56d9f2ecac662ca1611d183feb03a3fa4406469dafe241673d521dd5ae92a155 \
- --hash=sha256:5bbe06f8eeafd38e5d0a4894ffec89378b6c6a625ff57e3028921f8ff59318ac \
- --hash=sha256:65c1a9bcdadc6c28eecee2c119465aebff8f7a584dd719facdd9e825ec61ab52 \
- --hash=sha256:68e78619a61ecf91e76aa3e6e8e33fc4894a2bebe93410754bd28fce0a8a4f9f \
- --hash=sha256:69c0f17e9f5a7afdf2cc9fb2d1ce6aabdb3bafb7f38017c0b77862bcec2bbad8 \
- --hash=sha256:6b2b56950d93e41f33b4223ead100ea0fe11f8e6ee5f641eb753ce4b77a7042b \
- --hash=sha256:715d3562f79d540f251b99ebd6d8baa547118974341db04f5ad06d5ea3eb8007 \
- --hash=sha256:787003c0ddb00500e49a10f2844fac87aa6ce977b90b0feaaf9de23c22508b24 \
- --hash=sha256:7ef3cb2ebbf91e330e3bb937efada0edd9003683db6b57bb108c4001f37a02ea \
- --hash=sha256:8023faf4e01efadfa183e863fefde0046de576c6f14659e8782065bcece22198 \
- --hash=sha256:8758846a7e80910096950b67071243da3e5a20ed2546e6392603c096778d48e0 \
- --hash=sha256:8afafd99945ead6e075b973fefa56379c5b5c53fd8937dad92c662da5d8fd5ee \
- --hash=sha256:8c41976a29d078bb235fea9b2ecd3da465df42a562910f9022f1a03107bd02be \
- --hash=sha256:8e254ae696c88d98da6555f5ace2279cf7cd5b3f52be2b5cf97feafe883b58d2 \
- --hash=sha256:8f9293864fe09b8149f0cc42ce56e3f0e54de883a9de90cd427f191c346eb2e1 \
- --hash=sha256:9402b03f1a1b4dc4c19845e5c749e3ab82d5078d16a2a4c2cd2df62d57bb0707 \
- --hash=sha256:962f82a3086483f5e5f64dbad880d31038b698494799b097bc59c2edf392fce6 \
- --hash=sha256:9aad3c1755095ce347e26488214ef77e0485a3c34a50c5a5e2471dff60b9dd9c \
- --hash=sha256:9dcdfd0eaf283af041973bff14a2e143b8bd64e069f4c383416ecd79a81aab58 \
- --hash=sha256:aa57bd9cf8ae831a362185ee444e15a93ecb2e344c8e52e4d721ea3ab6ef1823 \
- --hash=sha256:aa7bd130efab1c280bed0f45501b7c8795f9fdbeb02e965371bbef3523627779 \
- --hash=sha256:ab4a0df41e7c16a1392727727e7998a467472d0ad65f3ad5e6e765015df08636 \
- --hash=sha256:ad9e82fb8f09ade1c3e1b996a6337afac2b8b9e365f926f5a61aacc71adc5b3c \
- --hash=sha256:af598ed32d6ae86f1b747b82783958b1a4ab8f617b06fe68795c7f026abbdcad \
- --hash=sha256:b076b6226fb84157e3f7c971a47ff3a679d837cf338547532ab866c57930dbee \
- --hash=sha256:b7ff0f54cb4ff66dd38bebd335a38e2c22c41a8ee45aa608efc890ac3e3931bc \
- --hash=sha256:bfce63a9e7834b12b87c64d6b155fdd9b3b96191b6bd334bf37db7ff1fe457f2 \
- --hash=sha256:c011a4149cfbcf9f03994ec2edffcb8b1dc2d2aede7ca243746df97a5d41ce48 \
- --hash=sha256:c9c804664ebe8f83a211cace637506669e7890fec1b4195b505c214e50dd4eb7 \
- --hash=sha256:ca379055a47383d02a5400cb0d110cef0a776fc644cda797db0c5696cfd7e18e \
- --hash=sha256:cb0932dc158471523c9637e807d9bfb93e06a95cbf010f1a38b98623b929ef2b \
- --hash=sha256:cd0f502fe016460680cd20aaa5a76d241d6f35a1c3350c474bac1273803893fa \
- --hash=sha256:ceb01949af7121f9fc39f7d27f91be8546f3fb112c608bc4029aef0bab86a2a5 \
- --hash=sha256:d080e0a5eb2529460b30190fcfcc4199bd7f827663f858a226a81bc27beaa97e \
- --hash=sha256:dd15ff04ffd7e05ffcb7fe79f1b98041b8ea30ae9234aed2a9168b5797c3effb \
- --hash=sha256:df0be2b576a7abbf737b1575f048c23fb1d769f267ec4358296f31c2479db8f9 \
- --hash=sha256:e09031c87a1e51556fdcb46e5bd4f59dfb743061cf93c4d6831bf894f125eb57 \
- --hash=sha256:e4dd52d80b8c83fdce44e12478ad2e85c64ea965e75d66dbeafb0a3e77308fcc \
- --hash=sha256:f698de3fd0c4e6972b92290a45bd9b1536bffe8c6759c62471efaa8acb4c37bc \
- --hash=sha256:fec21693218efe39aa7f8599346e90c705afa52c5b31ae019b2e57e8f6542bb2 \
- --hash=sha256:ffcc3f7c66b5f5b7931a5aa68fc9cecc51e685ef90282f4a82f0f5e9b704ad11
+markupsafe==2.1.4 \
+ --hash=sha256:0042d6a9880b38e1dd9ff83146cc3c9c18a059b9360ceae207805567aacccc69 \
+ --hash=sha256:0c26f67b3fe27302d3a412b85ef696792c4a2386293c53ba683a89562f9399b0 \
+ --hash=sha256:0fbad3d346df8f9d72622ac71b69565e621ada2ce6572f37c2eae8dacd60385d \
+ --hash=sha256:15866d7f2dc60cfdde12ebb4e75e41be862348b4728300c36cdf405e258415ec \
+ --hash=sha256:1c98c33ffe20e9a489145d97070a435ea0679fddaabcafe19982fe9c971987d5 \
+ --hash=sha256:21e7af8091007bf4bebf4521184f4880a6acab8df0df52ef9e513d8e5db23411 \
+ --hash=sha256:23984d1bdae01bee794267424af55eef4dfc038dc5d1272860669b2aa025c9e3 \
+ --hash=sha256:31f57d64c336b8ccb1966d156932f3daa4fee74176b0fdc48ef580be774aae74 \
+ --hash=sha256:3583a3a3ab7958e354dc1d25be74aee6228938312ee875a22330c4dc2e41beb0 \
+ --hash=sha256:36d7626a8cca4d34216875aee5a1d3d654bb3dac201c1c003d182283e3205949 \
+ --hash=sha256:396549cea79e8ca4ba65525470d534e8a41070e6b3500ce2414921099cb73e8d \
+ --hash=sha256:3a66c36a3864df95e4f62f9167c734b3b1192cb0851b43d7cc08040c074c6279 \
+ --hash=sha256:3aae9af4cac263007fd6309c64c6ab4506dd2b79382d9d19a1994f9240b8db4f \
+ --hash=sha256:3ab3a886a237f6e9c9f4f7d272067e712cdb4efa774bef494dccad08f39d8ae6 \
+ --hash=sha256:47bb5f0142b8b64ed1399b6b60f700a580335c8e1c57f2f15587bd072012decc \
+ --hash=sha256:49a3b78a5af63ec10d8604180380c13dcd870aba7928c1fe04e881d5c792dc4e \
+ --hash=sha256:4df98d4a9cd6a88d6a585852f56f2155c9cdb6aec78361a19f938810aa020954 \
+ --hash=sha256:5045e892cfdaecc5b4c01822f353cf2c8feb88a6ec1c0adef2a2e705eef0f656 \
+ --hash=sha256:5244324676254697fe5c181fc762284e2c5fceeb1c4e3e7f6aca2b6f107e60dc \
+ --hash=sha256:54635102ba3cf5da26eb6f96c4b8c53af8a9c0d97b64bdcb592596a6255d8518 \
+ --hash=sha256:54a7e1380dfece8847c71bf7e33da5d084e9b889c75eca19100ef98027bd9f56 \
+ --hash=sha256:55d03fea4c4e9fd0ad75dc2e7e2b6757b80c152c032ea1d1de487461d8140efc \
+ --hash=sha256:698e84142f3f884114ea8cf83e7a67ca8f4ace8454e78fe960646c6c91c63bfa \
+ --hash=sha256:6aa5e2e7fc9bc042ae82d8b79d795b9a62bd8f15ba1e7594e3db243f158b5565 \
+ --hash=sha256:7653fa39578957bc42e5ebc15cf4361d9e0ee4b702d7d5ec96cdac860953c5b4 \
+ --hash=sha256:765f036a3d00395a326df2835d8f86b637dbaf9832f90f5d196c3b8a7a5080cb \
+ --hash=sha256:78bc995e004681246e85e28e068111a4c3f35f34e6c62da1471e844ee1446250 \
+ --hash=sha256:7a07f40ef8f0fbc5ef1000d0c78771f4d5ca03b4953fc162749772916b298fc4 \
+ --hash=sha256:8b570a1537367b52396e53325769608f2a687ec9a4363647af1cded8928af959 \
+ --hash=sha256:987d13fe1d23e12a66ca2073b8d2e2a75cec2ecb8eab43ff5624ba0ad42764bc \
+ --hash=sha256:9896fca4a8eb246defc8b2a7ac77ef7553b638e04fbf170bff78a40fa8a91474 \
+ --hash=sha256:9e9e3c4020aa2dc62d5dd6743a69e399ce3de58320522948af6140ac959ab863 \
+ --hash=sha256:a0b838c37ba596fcbfca71651a104a611543077156cb0a26fe0c475e1f152ee8 \
+ --hash=sha256:a4d176cfdfde84f732c4a53109b293d05883e952bbba68b857ae446fa3119b4f \
+ --hash=sha256:a76055d5cb1c23485d7ddae533229039b850db711c554a12ea64a0fd8a0129e2 \
+ --hash=sha256:a76cd37d229fc385738bd1ce4cba2a121cf26b53864c1772694ad0ad348e509e \
+ --hash=sha256:a7cc49ef48a3c7a0005a949f3c04f8baa5409d3f663a1b36f0eba9bfe2a0396e \
+ --hash=sha256:abf5ebbec056817057bfafc0445916bb688a255a5146f900445d081db08cbabb \
+ --hash=sha256:b0fe73bac2fed83839dbdbe6da84ae2a31c11cfc1c777a40dbd8ac8a6ed1560f \
+ --hash=sha256:b6f14a9cd50c3cb100eb94b3273131c80d102e19bb20253ac7bd7336118a673a \
+ --hash=sha256:b83041cda633871572f0d3c41dddd5582ad7d22f65a72eacd8d3d6d00291df26 \
+ --hash=sha256:b835aba863195269ea358cecc21b400276747cc977492319fd7682b8cd2c253d \
+ --hash=sha256:bf1196dcc239e608605b716e7b166eb5faf4bc192f8a44b81e85251e62584bd2 \
+ --hash=sha256:c669391319973e49a7c6230c218a1e3044710bc1ce4c8e6eb71f7e6d43a2c131 \
+ --hash=sha256:c7556bafeaa0a50e2fe7dc86e0382dea349ebcad8f010d5a7dc6ba568eaaa789 \
+ --hash=sha256:c8f253a84dbd2c63c19590fa86a032ef3d8cc18923b8049d91bcdeeb2581fbf6 \
+ --hash=sha256:d18b66fe626ac412d96c2ab536306c736c66cf2a31c243a45025156cc190dc8a \
+ --hash=sha256:d5291d98cd3ad9a562883468c690a2a238c4a6388ab3bd155b0c75dd55ece858 \
+ --hash=sha256:d5c31fe855c77cad679b302aabc42d724ed87c043b1432d457f4976add1c2c3e \
+ --hash=sha256:d6e427c7378c7f1b2bef6a344c925b8b63623d3321c09a237b7cc0e77dd98ceb \
+ --hash=sha256:dac1ebf6983148b45b5fa48593950f90ed6d1d26300604f321c74a9ca1609f8e \
+ --hash=sha256:de8153a7aae3835484ac168a9a9bdaa0c5eee4e0bc595503c95d53b942879c84 \
+ --hash=sha256:e1a0d1924a5013d4f294087e00024ad25668234569289650929ab871231668e7 \
+ --hash=sha256:e7902211afd0af05fbadcc9a312e4cf10f27b779cf1323e78d52377ae4b72bea \
+ --hash=sha256:e888ff76ceb39601c59e219f281466c6d7e66bd375b4ec1ce83bcdc68306796b \
+ --hash=sha256:f06e5a9e99b7df44640767842f414ed5d7bedaaa78cd817ce04bbd6fd86e2dd6 \
+ --hash=sha256:f6be2d708a9d0e9b0054856f07ac7070fbe1754be40ca8525d5adccdbda8f475 \
+ --hash=sha256:f9917691f410a2e0897d1ef99619fd3f7dd503647c8ff2475bf90c3cf222ad74 \
+ --hash=sha256:fc1a75aa8f11b87910ffd98de62b29d6520b6d6e8a3de69a70ca34dea85d2a8a \
+ --hash=sha256:fe8512ed897d5daf089e5bd010c3dc03bb1bdae00b35588c49b98268d4a01e00
# via
# jinja2
# mkdocs
@@ -311,9 +311,9 @@ mkdocs==1.5.3 \
# -r requirements.in
# mike
# mkdocs-material
-mkdocs-material==9.5.3 \
- --hash=sha256:5899219f422f0a6de784232d9d40374416302ffae3c160cacc72969fcc1ee372 \
- --hash=sha256:76c93a8525cceb0b395b9cedab3428bf518cf6439adef2b940f1c1574b775d89
+mkdocs-material==9.5.4 \
+ --hash=sha256:3d196ee67fad16b2df1a458d650a8ac1890294eaae368d26cee71bc24ad41c40 \
+ --hash=sha256:efd7cc8ae03296d728da9bd38f4db8b07ab61f9738a0cbd0dfaf2a15a50e7343
# via
# -r requirements.in
# mkdocs-material
@@ -477,6 +477,7 @@ pyyaml==6.0.1 \
--hash=sha256:8d4e9c88387b0f5c7d5f281e55304de64cf7f9c0021a3525bd3b1c542da3b0e4 \
--hash=sha256:9046c58c4395dff28dd494285c82ba00b546adfc7ef001486fbf0324bc174fba \
--hash=sha256:9eb6caa9a297fc2c2fb8862bc5370d0303ddba53ba97e71f08023b6cd73d16a8 \
+ --hash=sha256:a08c6f0fe150303c1c6b71ebcd7213c2858041a7e01975da3a99aed1e7a378ef \
--hash=sha256:a0cd17c15d3bb3fa06978b4e8958dcdc6e0174ccea823003a106c7d4d7899ac5 \
--hash=sha256:afd7e57eddb1a54f0f1a974bc4391af8bcce0b444685d936840f125cf046d5bd \
--hash=sha256:b1275ad35a5d18c62a7220633c913e1b42d44b46ee12554e5fd39c70a243d6a3 \
diff --git a/docs/settings.md b/docs/settings.md
index 59dfc5c36..c346266b8 100644
--- a/docs/settings.md
+++ b/docs/settings.md
@@ -550,4 +550,3 @@ Allow access based on internal and external IP/network/rDNS/ASN whitelists.
|`WHITELIST_USER_AGENT_URLS`| |global |no |List of URLs, separated with spaces, containing good User-Agent to whitelist. |
|`WHITELIST_URI` | |multisite|no |List of URI (PCRE regex), separated with spaces, to whitelist. |
|`WHITELIST_URI_URLS` | |global |no |List of URLs, separated with spaces, containing bad URI to whitelist. |
-
diff --git a/docs/troubleshooting.md b/docs/troubleshooting.md
index 62a0aa736..ed966699a 100644
--- a/docs/troubleshooting.md
+++ b/docs/troubleshooting.md
@@ -465,4 +465,4 @@ In case you lost your UI credentials or have 2FA issues, you can connect to the
1|||0||(manual or ui)
```
- You should now be able to log into the web UI only using your username and password.
\ No newline at end of file
+ You should now be able to log into the web UI only using your username and password.
diff --git a/docs/web-ui.md b/docs/web-ui.md
index e8f3e9eb8..f02949633 100644
--- a/docs/web-ui.md
+++ b/docs/web-ui.md
@@ -37,7 +37,9 @@ Because the web UI is a web application, the recommended installation procedure
## Setup wizard
-The setup wizard is a feature that helps you to **configure** and **install the web UI** using a **user-friendly interface**. You will need to set the `UI_HOST` setting (`http://hostname-of-web-ui:7000`) and browse the `/setup` URI of your server to access the setup wizard.
+!!! info "Wizard"
+
+ The setup wizard is a feature that helps you to **configure** and **install the web UI** using a **user-friendly interface**. You will need to set the `UI_HOST` setting (`http://hostname-of-web-ui:7000`) and browse the `/setup` URI of your server to access the setup wizard.
{ align=center, width="350" }
@@ -66,6 +68,11 @@ Review your final BunkerWeb UI URL and then click on the `Setup` button. Once th
If you want to use the setup wizard, you will need to set the `UI_HOST` setting to the HTTP endpoint of your web UI container. For example, if your web UI container is named `bw-ui` and is listening on the `7000` port, you will need to set the `UI_HOST` setting to `http://bw-ui:7000`.
+ !!! tip "Accessing the setup wizard"
+
+ You can access the setup wizard by browsing the `http://your-ip-address/setup` URI of your server.
+
+
Here is the docker-compose boilerplate that you can use (don't forget to edit the `changeme` data) :
```yaml
@@ -153,6 +160,10 @@ Review your final BunkerWeb UI URL and then click on the `Setup` button. Once th
If you want to use the setup wizard, you will need to set the `UI_HOST` setting to the HTTP endpoint of your web UI container. For example, if your web UI container is named `bw-ui` and is listening on the `7000` port, you will need to set the `UI_HOST` setting to `http://bw-ui:7000`.
+ !!! tip "Accessing the setup wizard"
+
+ You can access the setup wizard by browsing the `http://your-ip-address/setup` URI of your server.
+
Here is the docker-compose boilerplate that you can use (don't forget to edit the `changeme` data) :
```yaml
@@ -256,6 +267,10 @@ Review your final BunkerWeb UI URL and then click on the `Setup` button. Once th
If you want to use the setup wizard, you will need to set the `UI_HOST` setting to the HTTP endpoint of your web UI container. For example, if your web UI container is named `bw-ui` and is listening on the `7000` port, you will need to set the `UI_HOST` setting to `http://bw-ui:7000`.
+ !!! tip "Accessing the setup wizard"
+
+ You can access the setup wizard by browsing the `http://your-ip-address/setup` URI of your server.
+
Here is the stack boilerplate that you can use (don't forget to edit the `changeme` data) :
```yaml
@@ -382,6 +397,10 @@ Review your final BunkerWeb UI URL and then click on the `Setup` button. Once th
If you want to use the setup wizard, you will need to set the `UI_HOST` setting to the HTTP endpoint of your web UI SERVICE. For example, if your web UI service is named `svc-bunkerweb-ui` and is listening on the `7000` port, you will need to set the `UI_HOST` setting to `http://svc-bunkerweb-ui:7000`.
+ !!! tip "Accessing the setup wizard"
+
+ You can access the setup wizard by browsing the `http://your-ip-address/setup` URI of your server.
+
Here is the yaml boilerplate that you can use (don't forget to edit the `changeme` data) :
```yaml
@@ -617,6 +636,7 @@ Review your final BunkerWeb UI URL and then click on the `Setup` button. Once th
labels:
app: bunkerweb-ui
spec:
+ serviceAccountName: sa-bunkerweb
containers:
- name: bunkerweb-ui
image: bunkerity/bunkerweb-ui:1.5.5
@@ -695,6 +715,10 @@ Review your final BunkerWeb UI URL and then click on the `Setup` button. Once th
If you want to use the setup wizard, you will need to set the `UI_HOST` setting to the HTTP endpoint of your web UI SERVICE. Since the web UI is listening on the same machine as BunkerWeb, you will need to set the `UI_HOST` setting `http://127.0.0.1:7000`.
+ !!! tip "Accessing the setup wizard"
+
+ You can access the setup wizard by browsing the `http://your-ip-address/setup` URI of your server.
+
Here is the `/etc/bunkerweb/variables.env` boilerplate you can use :
```conf
@@ -772,7 +796,7 @@ The following steps are needed to enable the TOTP feature from the web UI :
- Enter your current password
!!! info "Secret key refresh"
- A new secret key is **generated each time** you visit the page or submit the form. In case something went wrong (e.g. : expired TOTP code), you will need to copy the new secret key to your authenticator app until 2FA is successfuly enabled.
+ A new secret key is **generated each time** you visit the page or submit the form. In case something went wrong (e.g. : expired TOTP code), you will need to copy the new secret key to your authenticator app until 2FA is successfully enabled.
Once enabled, 2FA authentication can be disabled at the same place.
@@ -1452,6 +1476,7 @@ After a successful login/password combination, you will be prompted to enter you
labels:
app: bunkerweb-ui
spec:
+ serviceAccountName: sa-bunkerweb
containers:
- name: bunkerweb-ui
image: bunkerity/bunkerweb-ui:1.5.5
diff --git a/src/autoconf/Dockerfile b/src/autoconf/Dockerfile
index c2151afd9..a15fe88bc 100644
--- a/src/autoconf/Dockerfile
+++ b/src/autoconf/Dockerfile
@@ -1,4 +1,4 @@
-FROM python:3.12.1-alpine3.18@sha256:af0d8da43677e3000ebdf4045508d891a87e7bd2d3ec87bc6e40403be97291b8 AS builder
+FROM python:3.12.1-alpine3.18@sha256:fb759579d60cfe1f70b110a27be95aaa7cf758d2fa21cf54fffb71c2ba3f8034 AS builder
# Copy python requirements
COPY src/deps/requirements.txt /tmp/requirements-deps.txt
@@ -34,7 +34,7 @@ COPY src/common/helpers helpers
COPY src/common/settings.json settings.json
COPY src/common/utils utils
-FROM python:3.12.1-alpine3.18@sha256:af0d8da43677e3000ebdf4045508d891a87e7bd2d3ec87bc6e40403be97291b8
+FROM python:3.12.1-alpine3.18@sha256:fb759579d60cfe1f70b110a27be95aaa7cf758d2fa21cf54fffb71c2ba3f8034
# Set default umask to prevent huge recursive chmod increasing the final image size
RUN umask 027
@@ -64,7 +64,7 @@ RUN apk add --no-cache bash && \
chmod 750 cli/main.py helpers/*.sh /usr/bin/bwcli autoconf/main.py deps/python/bin/*
# Fix CVEs
-RUN apk add --no-cache "libcrypto3>=3.1.4-r3" "libssl3>=3.1.4-r3"
+RUN apk add --no-cache "libcrypto3>=3.1.4-r3" "libssl3>=3.1.4-r3" "sqlite-libs>=3.41.2-r3"
VOLUME /data /etc/nginx
diff --git a/src/autoconf/SwarmController.py b/src/autoconf/SwarmController.py
index dd415f364..9ec837f7e 100644
--- a/src/autoconf/SwarmController.py
+++ b/src/autoconf/SwarmController.py
@@ -125,7 +125,7 @@ class SwarmController(Controller):
def __process_event(self, event):
if "Actor" not in event or "ID" not in event["Actor"] or "Type" not in event:
return False
- if event["Type"] not in ["service", "config"]:
+ if event["Type"] not in ("service", "config"):
return False
if event["Type"] == "service":
if event["Actor"]["ID"] in self.__swarm_instances or event["Actor"]["ID"] in self.__swarm_services:
diff --git a/src/bw/Dockerfile b/src/bw/Dockerfile
index 78fc5a6ea..adaa9451b 100644
--- a/src/bw/Dockerfile
+++ b/src/bw/Dockerfile
@@ -78,7 +78,7 @@ RUN apk add --no-cache pcre bash python3 yajl && \
ln -s /proc/1/fd/1 /var/log/bunkerweb/access.log
# Fix CVEs
-RUN apk add --no-cache "libwebp>=1.2.4-r3" "curl>=8.3.0-r0" "libcurl>=8.3.0-r0" "nghttp2-libs>=1.51.0-r2" "libcrypto3>=3.0.12-r0" "libssl3>=3.0.12-r0" "libx11>=1.8.7-r0"
+RUN apk add --no-cache "libwebp>=1.2.4-r3" "curl>=8.3.0-r0" "libcurl>=8.3.0-r0" "nghttp2-libs>=1.51.0-r2" "libx11>=1.8.7-r0" "libssl3>=3.0.12-r1" "libcrypto3>=3.0.12-r1"
EXPOSE 8080/tcp 8443/tcp
diff --git a/src/bw/lua/bunkerweb/api.lua b/src/bw/lua/bunkerweb/api.lua
index 9c2f9a2a8..abbcf4b2e 100644
--- a/src/bw/lua/bunkerweb/api.lua
+++ b/src/bw/lua/bunkerweb/api.lua
@@ -33,7 +33,6 @@ local get_body_data = ngx_req.get_body_data
local get_body_file = ngx_req.get_body_file
local decode = cjson.decode
local encode = cjson.encode
-local floor = math.floor
local match = string.match
local require_plugin = helpers.require_plugin
local new_plugin = helpers.new_plugin
@@ -216,7 +215,26 @@ api.global.POST["^/ban$"] = function(self)
if not ok then
return self:response(HTTP_INTERNAL_SERVER_ERROR, "error", "can't decode JSON : " .. ip)
end
- datastore:set("bans_ip_" .. ip["ip"], "manual", ip["exp"])
+ local ban = {
+ ip = "",
+ exp = 86400,
+ reason = "manual",
+ }
+ ban.ip = ip["ip"]
+ if ip["exp"] then
+ ban.exp = ip["exp"]
+ end
+ if ip["reason"] then
+ ban.reason = ip["reason"]
+ end
+ datastore:set(
+ "bans_ip_" .. ban["ip"],
+ encode({
+ reason = ban["reason"],
+ date = os.time(),
+ }),
+ ban["exp"]
+ )
return self:response(HTTP_OK, "success", "ip " .. ip["ip"] .. " banned")
end
@@ -224,12 +242,12 @@ api.global.GET["^/bans$"] = function(self)
local data = {}
for _, k in ipairs(datastore:keys()) do
if k:find("^bans_ip_") then
- local reason, err = datastore:get(k)
+ local result, err = datastore:get(k)
if err then
return self:response(
HTTP_INTERNAL_SERVER_ERROR,
"error",
- "can't access " .. k .. " from datastore : " .. reason
+ "can't access " .. k .. " from datastore : " .. result
)
end
local ok, ttl = datastore:ttl(k)
@@ -240,7 +258,9 @@ api.global.GET["^/bans$"] = function(self)
"can't access ttl " .. k .. " from datastore : " .. ttl
)
end
- local ban = { ip = k:sub(9, #k), reason = reason, exp = floor(ttl) }
+ local ban_data = decode(result)
+ local ban =
+ { ip = k:sub(9, #k), reason = ban_data["reason"], date = ban_data["date"], exp = math.floor(ttl) }
table.insert(data, ban)
end
end
diff --git a/src/bw/lua/bunkerweb/clusterstore.lua b/src/bw/lua/bunkerweb/clusterstore.lua
index ec7545afe..794f31938 100644
--- a/src/bw/lua/bunkerweb/clusterstore.lua
+++ b/src/bw/lua/bunkerweb/clusterstore.lua
@@ -2,7 +2,6 @@ local ngx = ngx
local class = require "middleclass"
local clogger = require "bunkerweb.logger"
local rc = require "resty.redis.connector"
-local rs = require("resty.redis.sentinel")
local utils = require "bunkerweb.utils"
local clusterstore = class("clusterstore")
@@ -12,10 +11,10 @@ local logger = clogger:new("CLUSTERSTORE")
local get_variable = utils.get_variable
local is_cosocket_available = utils.is_cosocket_available
local ERR = ngx.ERR
+local WARN = ngx.WARN
local INFO = ngx.INFO
local tonumber = tonumber
local tostring = tostring
-local random = math.random
function clusterstore:initialize(pool)
-- Get variables
@@ -25,6 +24,7 @@ function clusterstore:initialize(pool)
["REDIS_PORT"] = "",
["REDIS_DATABASE"] = "",
["REDIS_SSL"] = "",
+ ["REDIS_SSL_VERIFY"] = "",
["REDIS_TIMEOUT"] = "",
["REDIS_KEEPALIVE_IDLE"] = "",
["REDIS_KEEPALIVE_POOL"] = "",
@@ -57,6 +57,7 @@ function clusterstore:initialize(pool)
keepalive_poolsize = tonumber(self.variables["REDIS_KEEPALIVE_POOL"]),
connection_options = {
ssl = self.variables["REDIS_SSL"] == "yes",
+ ssl_verify = self.variables["REDIS_SSL_VERIFY"] == "yes",
},
host = self.variables["REDIS_HOST"],
port = tonumber(self.variables["REDIS_PORT"]),
@@ -71,7 +72,6 @@ function clusterstore:initialize(pool)
}
self.pool = pool == nil or pool
if self.pool then
- options.connection_options.pool = "bw-redis"
options.connection_options.pool_size = tonumber(self.variables["REDIS_KEEPALIVE_POOL"])
end
if self.variables["REDIS_SENTINEL_HOSTS"] ~= "" then
@@ -82,7 +82,14 @@ function clusterstore:initialize(pool)
else
sport = tonumber(sport)
end
- table.insert(options.sentinel, { host = shost, port = sport })
+ local data = { host = shost, port = sport }
+ if options.sentinel_username ~= "" then
+ data.username = options.sentinel_username
+ end
+ if options.sentinel_password ~= "" then
+ data.password = options.sentinel_password
+ end
+ table.insert(options.sentinels, data)
end
end
self.options = options
@@ -107,33 +114,37 @@ function clusterstore:connect(readonly)
self:close()
end
-- Connect to sentinels if needed
- local redis_client, err
- if #self.options.sentinels > 0 then
- local redis_sentinel
- redis_sentinel, err = self.redis_connector:connect()
- if not redis_sentinel then
- return false, "error while connecting to sentinels : " .. err
- end
- if readonly then
- local redis_clients, _ = rs.get_slaves(redis_sentinel, self.options.master_name)
- if redis_clients then
- redis_client = redis_clients[random(#redis_clients)]
- else
- redis_client = nil
+ local redis_client, err, previous_errors
+ if #self.options.sentinels > 0 and readonly then
+ redis_client, err, previous_errors = self.redis_connector:connect({ role = "slave" })
+ if not redis_client then
+ if previous_errors then
+ err = err .. " ( previous errors : "
+ for _, e in ipairs(previous_errors) do
+ err = err .. e .. ", "
+ end
+ err = err:sub(1, -3) .. " )"
end
- else
- redis_client, err = rs.get_master(redis_sentinel, self.options.master_name)
+ logger:log(WARN, "error while getting redis slave client : " .. err .. ", fallback to master")
+ redis_client, err, previous_errors = self.redis_connector:connect()
end
- -- Classic connection
else
- redis_client, err = self.redis_connector:connect()
+ redis_client, err, previous_errors = self.redis_connector:connect()
end
self.redis_client = redis_client
if not self.redis_client then
+ if previous_errors then
+ err = err .. " ( previous errors : "
+ for _, e in ipairs(previous_errors) do
+ err = err .. e .. ", "
+ end
+ err = err:sub(1, -3) .. " )"
+ end
return false, "error while getting redis client : " .. err
end
-- Everything went well
- local times, err = self.redis_client:get_reused_times()
+ local times
+ times, err = self.redis_client:get_reused_times()
if times == nil then
self:close()
return false, "error while getting reused times : " .. err
diff --git a/src/bw/lua/bunkerweb/datastore.lua b/src/bw/lua/bunkerweb/datastore.lua
index c720d453a..72f86054f 100644
--- a/src/bw/lua/bunkerweb/datastore.lua
+++ b/src/bw/lua/bunkerweb/datastore.lua
@@ -15,8 +15,10 @@ if not lru then
logger:log(ERR, "failed to instantiate LRU cache : " .. err_lru)
end
-function datastore:initialize()
- if subsystem == "http" then
+function datastore:initialize(dict)
+ if dict then
+ self.dict = dict
+ elseif subsystem == "http" then
self.dict = shared.datastore
else
self.dict = shared.datastore_stream
@@ -112,4 +114,32 @@ function datastore:flush_lru()
lru:flush_all()
end
+function datastore:safe_rpush(key, value)
+ local length, err = self.dict:rpush(key, value)
+ if not length and err == "no memory" then
+ local i = 0
+ while i < 5 do
+ local val
+ val, err = self.dict:lpop(key)
+ if not val then
+ return val, err
+ end
+ length, err = self.dict:rpush(key, value)
+ if not length and err ~= "no memory" then
+ return length, err
+ end
+ i = i + 1
+ end
+ end
+ return length, err
+end
+
+function datastore:lpop(key)
+ return self.dict:lpop(key)
+end
+
+function datastore:llen(key)
+ return self.dict:llen(key)
+end
+
return datastore
diff --git a/src/bw/lua/bunkerweb/helpers.lua b/src/bw/lua/bunkerweb/helpers.lua
index f417f2e04..3c41fa82f 100644
--- a/src/bw/lua/bunkerweb/helpers.lua
+++ b/src/bw/lua/bunkerweb/helpers.lua
@@ -185,6 +185,7 @@ helpers.fill_ctx = function(no_ref)
end
data.remote_addr = var.remote_addr
data.server_name = var.server_name
+ data.local_time = var.local_time
if data.kind == "http" then
data.uri = var.uri
data.request_uri = var.request_uri
diff --git a/src/bw/lua/bunkerweb/utils.lua b/src/bw/lua/bunkerweb/utils.lua
index 9b381c680..4b163ebca 100644
--- a/src/bw/lua/bunkerweb/utils.lua
+++ b/src/bw/lua/bunkerweb/utils.lua
@@ -29,7 +29,6 @@ local decode = cjson.decode
local char = string.char
local random = math.random
local session_start = session.start
-local session_open = session.open
local tonumber = tonumber
local utils = {}
@@ -318,7 +317,7 @@ utils.get_reason = function(ctx)
end
local banned, _ = datastore:get("bans_ip_" .. ip)
if banned then
- return banned, {}
+ return decode(banned)["reason"], {}
end
-- unknown
if ngx.status == utils.get_deny_status() then
@@ -569,86 +568,86 @@ utils.get_deny_status = function()
return 444
end
-utils.check_session = function(ctx)
- local _session, _, exists, _ = session_start({ audience = "metadata" })
+utils.get_session = function(ctx)
+ -- Return session from ctx if already there
+ if ctx.bw.sessions_session then
+ return ctx.bw.sessions_session
+ end
+ -- Open/create and do an optional refresh
+ local err, exists, refreshed
+ session, err, exists, refreshed = session_start()
+ if not session then
+ return nil, err
+ end
+ if err then
+ logger:log(WARN, "can't open session : " .. err)
+ end
+ local checks = {
+ ["IP"] = ctx.bw.remote_addr,
+ ["USER_AGENT"] = ctx.bw.http_user_agent or "",
+ }
if exists then
- for _, check in ipairs(ctx.bw.sessions_checks) do
- local key = check[1]
- local value = check[2]
- if _session:get(key) ~= value then
- _session:clear_request_cookie()
- local ok, err = _session:destroy()
- if not ok then
- return false, "session:destroy() error : " .. err
+ logger:log(INFO, "opening an existing session")
+ if refreshed then
+ logger:log(INFO, "existing session refreshed")
+ end
+ -- Get metadata
+ local metadata = session:get("metadata")
+ if metadata then
+ -- Check if session passes the checks
+ for check, value in pairs(checks) do
+ local check_value
+ check_value, err = utils.get_variable("SESSIONS_CHECK_" .. check, false, nil)
+ if not check_value then
+ logger:log(ERR, "error while getting variable SESSIONS_CHECK_" .. check .. " : " .. err)
+ elseif check_value == "yes" and value ~= metadata[check] then
+ logger:log(WARN, "session check failed : " .. check .. "!=" .. metadata[check])
+ local ok
+ ok, err = session:destroy()
+ if not ok then
+ return nil, err
+ end
+ return utils.get_session(ctx)
end
- logger:log(WARN, "session check " .. key .. " failed, destroying session")
- return utils.check_session(ctx)
end
end
else
- for _, check in ipairs(ctx.bw.sessions_checks) do
- _session:set(check[1], check[2])
- end
- local ok, err = _session:save()
- if not ok then
- _session:close()
- return false, "session:save() error : " .. err
- end
+ logger:log(INFO, "creating a new session")
+ session:set("metadata", checks)
+ ctx.bw.sessions_updated = true
end
- ctx.bw.sessions_is_checked = true
- return true, exists
+ ctx.bw.sessions_session = session
+ return session
end
-utils.get_session = function(audience, ctx)
- -- Check session
- if not ctx.bw.sessions_is_checked then
- local ok, err = utils.check_session(ctx)
- if not ok then
- return false, "error while checking session, " .. err
+utils.save_session = function(ctx)
+ if ctx.bw.sessions_session then
+ if ctx.bw.sessions_updated then
+ local ok, err = ctx.bw.sessions_session:save()
+ if not err then
+ err = "session saved"
+ end
+ return ok, err
+ else
+ return true, "session not updated"
end
+ else
+ return true, "no session"
end
- -- Open session with specific audience
- local _session, err, _ = session_open({ audience = audience })
- if err then
- logger:log(INFO, "session:open() error : " .. err)
- end
- return _session
-end
-
--- luacheck: ignore 214
-utils.get_session_data = function(_session, site, ctx)
- local site_only = site == nil or site
- local data = _session:get_data()
- if site_only then
- return data[ctx.bw.server_name] or {}
- end
- return data
-end
-
--- luacheck: ignore 214
-utils.set_session_data = function(_session, data, site, ctx)
- local site_only = site == nil or site
- if site_only then
- local all_data = _session:get_data()
- all_data[ctx.bw.server_name] = data
- _session:set_data(all_data)
- return _session:save()
- end
- _session:set_data(data)
- return _session:save()
end
utils.is_banned = function(ip)
-- Check on local datastore
- local reason, err = datastore:get("bans_ip_" .. ip)
- if not reason and err ~= "not found" then
- return nil, "datastore:get() error : " .. reason
- elseif reason and err ~= "not found" then
+ local result, err = datastore:get("bans_ip_" .. ip)
+ if not result and err ~= "not found" then
+ return nil, "datastore:get() error : " .. result
+ elseif result and err ~= "not found" then
local ok, ttl = datastore:ttl("bans_ip_" .. ip)
+ local ban_data = decode(result)
if not ok then
- return true, reason, -1
+ return true, ban_data["reason"], -1
end
- return true, reason, ttl
+ return true, ban_data["reason"], ttl
end
-- Redis case
local use_redis, err = utils.get_variable("USE_REDIS", false)
@@ -695,7 +694,7 @@ utils.is_banned = function(ip)
if not ok then
return nil, "datastore:set() error : " .. err
end
- return true, data[1], data[2]
+ return true, decode(data[1])["reason"], data[2]
end
clusterstore:close()
return false, "not banned"
@@ -703,7 +702,11 @@ end
utils.add_ban = function(ip, reason, ttl)
-- Set on local datastore
- local ok, err = datastore:set("bans_ip_" .. ip, reason, ttl)
+ local ban_data = encode({
+ reason = reason,
+ date = os.time(),
+ })
+ local ok, err = datastore:set("bans_ip_" .. ip, ban_data, ttl)
if not ok then
return false, "datastore:set() error : " .. err
end
@@ -721,7 +724,7 @@ utils.add_ban = function(ip, reason, ttl)
return false, "can't connect to redis server : " .. err
end
-- SET call
- ok, err = clusterstore:call("set", "bans_ip_" .. ip, reason, "EX", ttl)
+ ok, err = clusterstore:call("set", "bans_ip_" .. ip, ban_data, "EX", ttl)
if not ok then
clusterstore:close()
return false, "redis SET failed : " .. err
diff --git a/src/common/cli/CLI.py b/src/common/cli/CLI.py
index b8b6cf754..1dfb13832 100644
--- a/src/common/cli/CLI.py
+++ b/src/common/cli/CLI.py
@@ -1,12 +1,15 @@
#!/usr/bin/env python3
+from datetime import datetime
+from json import dumps, loads
+from time import time
from dotenv import dotenv_values
from os import getenv, sep
from os.path import join
from pathlib import Path
-from redis import StrictRedis
+from redis import StrictRedis, Sentinel
from sys import path as sys_path
-from typing import Optional, Tuple
+from typing import Any, Optional, Tuple
for deps_path in [join(sep, "usr", "share", "bunkerweb", *paths) for paths in (("utils",), ("db",))]:
@@ -19,10 +22,19 @@ from logger import setup_logger # type: ignore
def format_remaining_time(seconds):
- days, seconds = divmod(seconds, 86400)
- hours, seconds = divmod(seconds, 3600)
+ years, seconds = divmod(seconds, 60 * 60 * 24 * 365)
+ months, seconds = divmod(seconds, 60 * 60 * 24 * 30)
+ while months >= 12:
+ years += 1
+ months -= 12
+ days, seconds = divmod(seconds, 60 * 60 * 24)
+ hours, seconds = divmod(seconds, 60 * 60)
minutes, seconds = divmod(seconds, 60)
time_parts = []
+ if years > 0:
+ time_parts.append(f"{int(years)} year{'' if years == 1 else 's'}")
+ if months > 0:
+ time_parts.append(f"{int(months)} month{'' if months == 1 else 's'}")
if days > 0:
time_parts.append(f"{int(days)} day{'' if days == 1 else 's'}")
if hours > 0:
@@ -49,6 +61,8 @@ class CLI(ApiCaller):
if Path(sep, "usr", "share", "bunkerweb", "db").exists():
from Database import Database # type: ignore
+ self.__logger.info("Getting variables from database")
+
db = Database(self.__logger, sqlalchemy_string=self.__get_variable("DATABASE_URI", None))
self.__variables = db.get_config()
@@ -58,6 +72,7 @@ class CLI(ApiCaller):
self.__use_redis = self.__get_variable("USE_REDIS", "no") == "yes"
self.__redis = None
if self.__use_redis:
+ self.__logger.info("Fetching redis configuration")
redis_host = self.__get_variable("REDIS_HOST")
if redis_host:
redis_port = self.__get_variable("REDIS_PORT", "6379")
@@ -89,16 +104,71 @@ class CLI(ApiCaller):
redis_keepalive_pool = "10"
redis_keepalive_pool = int(redis_keepalive_pool)
- self.__redis = StrictRedis(
- host=redis_host,
- port=redis_port,
- db=redis_db,
- socket_timeout=redis_timeout,
- socket_connect_timeout=redis_timeout,
- socket_keepalive=True,
- max_connections=redis_keepalive_pool,
- ssl=self.__get_variable("REDIS_SSL", "no") == "yes",
- )
+ self.__logger.info("Redis configuration is valid")
+
+ redis_ssl = self.__get_variable("REDIS_SSL", "no") == "yes"
+ username = self.__get_variable("REDIS_USERNAME", None) or None
+ password = self.__get_variable("REDIS_PASSWORD", None) or None
+ sentinel_hosts = self.__get_variable("REDIS_SENTINEL_HOSTS", [])
+
+ if isinstance(sentinel_hosts, str):
+ sentinel_hosts = [host.split(":") if ":" in host else host for host in sentinel_hosts.split(" ") if host]
+
+ if sentinel_hosts:
+ sentinel_username = self.__get_variable("REDIS_SENTINEL_USERNAME", None) or None
+ sentinel_password = self.__get_variable("REDIS_SENTINEL_PASSWORD", None) or None
+ sentinel_master = self.__get_variable("REDIS_SENTINEL_MASTER", "")
+
+ self.__logger.info(
+ f"Connecting to redis sentinel cluster with the following parameters:\n{sentinel_hosts=}\n{sentinel_username=}\n{sentinel_password=}\n{sentinel_master=}\n{redis_timeout=}\nmax_connections={redis_keepalive_pool}\n{redis_ssl=}"
+ )
+ sentinel = Sentinel(
+ sentinel_hosts,
+ username=sentinel_username,
+ password=sentinel_password,
+ ssl=redis_ssl,
+ socket_timeout=redis_timeout,
+ socket_connect_timeout=redis_timeout,
+ socket_keepalive=True,
+ max_connections=redis_keepalive_pool,
+ )
+ try:
+ sentinel.discover_master(sentinel_master)
+ except Exception as e:
+ self.__logger.error(f"Failed to connect to redis sentinel cluster: {e}, disabling redis")
+ self.__use_redis = False
+
+ if self.__use_redis:
+ self.__logger.info(f"Connected to redis sentinel cluster, getting master with the following parameters:\n{sentinel_master=}\n{redis_db=}\n{username=}\n{password=}")
+ self.__redis = sentinel.master_for(
+ sentinel_master,
+ db=redis_db,
+ username=username,
+ password=password,
+ )
+ else:
+ self.__logger.info(f"Connecting to redis with the following parameters:\n{redis_host=}\n{redis_port=}\n{redis_db=}\n{username=}\n{password=}\n{redis_timeout=}\nmax_connections={redis_keepalive_pool}\n{redis_ssl=}")
+ self.__redis = StrictRedis(
+ host=redis_host,
+ port=redis_port,
+ db=redis_db,
+ username=username,
+ password=password,
+ socket_timeout=redis_timeout,
+ socket_connect_timeout=redis_timeout,
+ socket_keepalive=True,
+ max_connections=redis_keepalive_pool,
+ ssl=redis_ssl,
+ )
+
+ try:
+ if self.__use_redis:
+ assert self.__redis, "Redis connection is None"
+ self.__redis.ping()
+ except Exception as e:
+ self.__logger.error(f"Failed to connect to redis: {e}, disabling redis")
+ self.__use_redis = False
+ self.__logger.info("Connected to redis")
else:
self.__logger.error("USE_REDIS is set to yes but REDIS_HOST is not set, disabling redis")
self.__use_redis = False
@@ -116,7 +186,7 @@ class CLI(ApiCaller):
super().__init__()
self.auto_setup(self.__integration)
- def __get_variable(self, variable: str, default: Optional[str] = None) -> Optional[str]:
+ def __get_variable(self, variable: str, default: Optional[Any] = None) -> Optional[str]:
return getenv(variable, self.__variables.get(variable, default))
def __detect_integration(self) -> str:
@@ -148,14 +218,15 @@ class CLI(ApiCaller):
return True, f"IP {ip} has been unbanned"
return False, "error"
- def ban(self, ip: str, exp: float) -> Tuple[bool, str]:
+ def ban(self, ip: str, exp: float, reason: str) -> Tuple[bool, str]:
if self.__redis:
- ok = self.__redis.set(f"bans_ip_{ip}", "manual", ex=exp)
+ ok = self.__redis.set(f"bans_ip_{ip}", dumps({"reason": reason, "date": time()}))
if not ok:
self.__logger.error(f"Failed to ban {ip} in redis")
+ self.__redis.expire(f"bans_ip_{ip}", int(exp))
- if self.send_to_apis("POST", "/ban", data={"ip": ip, "exp": exp}):
- return (True, f"IP {ip} has been banned for {format_remaining_time(exp)}")
+ if self.send_to_apis("POST", "/ban", data={"ip": ip, "exp": exp, "reason": reason}):
+ return (True, f"IP {ip} has been banned for {format_remaining_time(exp)} with reason {reason}")
return False, "error"
def bans(self) -> Tuple[bool, str]:
@@ -172,8 +243,13 @@ class CLI(ApiCaller):
servers["redis"] = []
for key in self.__redis.scan_iter("bans_ip_*"):
ip = key.decode("utf-8").replace("bans_ip_", "")
+ data = self.__redis.get(key)
+ if not data:
+ continue
exp = self.__redis.ttl(key)
- servers["redis"].append({"ip": ip, "exp": exp, "reason": "manual"})
+ servers["redis"].append({"ip": ip, "exp": exp} | loads(data))
+
+ servers = {k: sorted(v, key=lambda x: x["date"]) for k, v in servers.items()}
cli_str = ""
for server, bans in servers.items():
@@ -182,7 +258,7 @@ class CLI(ApiCaller):
cli_str += "No ban found\n"
for ban in bans:
- cli_str += f"- {ban['ip']} for {format_remaining_time(ban['exp'])} : {ban.get('reason', 'no reason given')}\n"
+ cli_str += f"- {ban['ip']} ; banned the {datetime.fromtimestamp(ban['date']).strftime('%d-%m-%Y at %H:%M:%S')} for {format_remaining_time(ban['exp'])} remaining with reason \"{ban.get('reason', 'no reason given')}\"\n"
cli_str += "\n"
return True, cli_str
diff --git a/src/common/cli/main.py b/src/common/cli/main.py
index 92473b7c7..486e8f5d2 100644
--- a/src/common/cli/main.py
+++ b/src/common/cli/main.py
@@ -40,6 +40,12 @@ if __name__ == "__main__":
help=f"banning time in seconds (default : {ban_time})",
default=ban_time,
)
+ parser_ban.add_argument(
+ "-reason",
+ type=str,
+ help="reason for ban (default : manual)",
+ default="manual",
+ )
# Bans subparser
parser_bans = subparsers.add_parser("bans", help="list current bans")
@@ -55,7 +61,7 @@ if __name__ == "__main__":
if args.command == "unban":
ret, err = cli.unban(args.ip)
elif args.command == "ban":
- ret, err = cli.ban(args.ip, args.exp)
+ ret, err = cli.ban(args.ip, args.exp, args.reason)
elif args.command == "bans":
ret, err = cli.bans()
diff --git a/src/common/confs/server-http/access-lua.conf b/src/common/confs/server-http/access-lua.conf
index a707fcebb..1de1793df 100644
--- a/src/common/confs/server-http/access-lua.conf
+++ b/src/common/confs/server-http/access-lua.conf
@@ -22,6 +22,7 @@ access_by_lua_block {
local is_banned = utils.is_banned
local set_reason = utils.set_reason
local get_deny_status = utils.get_deny_status
+ local save_session = utils.save_session
local tostring = tostring
-- Don't process internal requests
@@ -120,6 +121,14 @@ access_by_lua_block {
end
logger:log(INFO, "called access() methods of plugins")
+ -- Save session
+ ok, err = save_session(ctx)
+ if ok then
+ logger:log(INFO, err)
+ else
+ logger:log(ERR, err)
+ end
+
-- Save ctx
save_ctx(ctx)
diff --git a/src/common/core/antibot/antibot.lua b/src/common/core/antibot/antibot.lua
index 14cab8f9e..d7ef474f2 100644
--- a/src/common/core/antibot/antibot.lua
+++ b/src/common/core/antibot/antibot.lua
@@ -12,11 +12,10 @@ local ngx = ngx
local subsystem = ngx.config.subsystem
local HTTP_INTERNAL_SERVER_ERROR = ngx.HTTP_INTERNAL_SERVER_ERROR
local OK = ngx.OK
+local INFO = ngx.INFO
local tonumber = tonumber
local tostring = tostring
local get_session = utils.get_session
-local get_session_data = utils.get_session_data
-local set_session_data = utils.set_session_data
local get_deny_status = utils.get_deny_status
local rand = utils.rand
local now = ngx.now
@@ -46,37 +45,26 @@ function antibot:header()
return self:ret(true, "antibot not activated")
end
-- Check if antibot uri
- if self.ctx.bw.uri ~= self.variables["ANTIBOT_URI"] then
- return self:ret(true, "Not antibot uri")
- end
-
- -- Get session data
- local session, err = get_session("antibot", self.ctx)
- if not session then
- return self:ret(false, "can't get session : " .. err, HTTP_INTERNAL_SERVER_ERROR)
- end
- self.session = session
- self.session_data = get_session_data(self.session, true, self.ctx)
- -- Check if session is valid
- self:check_session()
-
- -- Don't go further if client resolved the challenge
- if self.session_data.resolved then
- if self.ctx.bw.uri == self.variables["ANTIBOT_URI"] then
- return self:ret(true, "client already resolved the challenge", nil, self.session_data.original_uri)
- end
- return self:ret(true, "client already resolved the challenge")
- end
-
if self.ctx.bw.uri ~= self.variables["ANTIBOT_URI"] then
return self:ret(true, "not antibot uri")
end
+ -- Get session data
+ self.session_data = self.ctx.bw.antibot_session_data
+ if not self.session_data then
+ return self:ret(false, "can't get session data", HTTP_INTERNAL_SERVER_ERROR)
+ end
+
+ -- Don't go further if client resolved the challenge
+ if self.session_data.resolved then
+ return self:ret(true, "client already resolved the challenge", nil, self.session_data.original_uri)
+ end
+
+ -- Override headers
local header = "Content-Security-Policy"
if self.variables["CONTENT_SECURITY_POLICY_REPORT_ONLY"] == "yes" then
header = header .. "-Report-Only"
end
-
if self.session_data.type == "recaptcha" then
ngx.header[header] = "default-src 'none'; form-action 'self'; script-src 'strict-dynamic' 'nonce-"
.. self.session_data.nonce_script
@@ -108,7 +96,7 @@ function antibot:header()
.. self.session_data.nonce_style
.. "'; font-src 'self' data:; base-uri 'self';"
end
- return self:ret(true, "Successfully overridden CSP header")
+ return self:ret(true, "successfully overridden CSP header")
end
function antibot:access()
@@ -118,14 +106,17 @@ function antibot:access()
end
-- Get session data
- local session, err = get_session("antibot", self.ctx)
+ local session, err = get_session(self.ctx)
if not session then
- return self:ret(false, "can't get session : " .. err, HTTP_INTERNAL_SERVER_ERROR)
+ return self:ret(false, "can't get session : " .. err)
end
self.session = session
- self.session_data = get_session_data(self.session, true, self.ctx)
+ self.session_data = session:get("antibot") or {}
+ self.ctx.bw.antibot_session_data = self.session_data
+
-- Check if session is valid
- self:check_session()
+ local msg = self:check_session()
+ self.logger:log(INFO, "check_session returned : " .. msg)
-- Don't go further if client resolved the challenge
if self.session_data.resolved then
@@ -137,10 +128,6 @@ function antibot:access()
-- Prepare challenge if needed
self:prepare_challenge()
- local ok, err = self:set_session_data()
- if not ok then
- return self:ret(false, "can't save session : " .. err, HTTP_INTERNAL_SERVER_ERROR)
- end
-- Redirect to challenge page
if self.ctx.bw.uri ~= self.variables["ANTIBOT_URI"] then
@@ -162,10 +149,6 @@ function antibot:access()
if self.ctx.bw.request_method == "POST" then
-- luacheck: ignore 421
local ok, err, redirect = self:check_challenge()
- local set_ok, set_err = self:set_session_data()
- if not set_ok then
- return self:ret(false, "can't save session : " .. set_err, HTTP_INTERNAL_SERVER_ERROR)
- end
if ok == nil then
return self:ret(false, "check challenge error : " .. err, HTTP_INTERNAL_SERVER_ERROR)
elseif not ok then
@@ -175,10 +158,6 @@ function antibot:access()
return self:ret(true, "check challenge redirect : " .. redirect, nil, redirect)
end
self:prepare_challenge()
- ok, err = self:set_session_data()
- if not ok then
- return self:ret(false, "can't save session : " .. err, HTTP_INTERNAL_SERVER_ERROR)
- end
self.ctx.bw.antibot_display_content = true
return self:ret(true, "displaying challenge to client", OK)
end
@@ -202,12 +181,10 @@ function antibot:content()
end
-- Get session data
- local session, err = get_session("antibot", self.ctx)
- if not session then
- return self:ret(false, "can't get session : " .. err, HTTP_INTERNAL_SERVER_ERROR)
+ self.session_data = self.ctx.bw.antibot_session_data
+ if not self.session_data then
+ return self:ret(false, "missing session data", HTTP_INTERNAL_SERVER_ERROR)
end
- self.session = session
- self.session_data = get_session_data(self.session, true, self.ctx)
-- Direct access without session
if not self.session_data.prepared then
@@ -229,42 +206,36 @@ function antibot:check_session()
-- Not resolved and not prepared
if not time_resolve and not time_valid then
self.session_data = {}
- self.session_updated = true
- return
+ self:set_session_data()
+ return "not prepared"
end
-- Check if still valid
- local time = ngx.now()
+ local time = now()
local resolved = self.session_data.resolved
if resolved and (time_valid > time or time - time_valid > tonumber(self.variables["ANTIBOT_TIME_VALID"])) then
self.session_data = {}
- self.session_updated = true
- return
+ self:set_session_data()
+ return "need new resolve"
end
-- Check if new prepare is needed
if
not resolved and (time_resolve > time or time - time_resolve > tonumber(self.variables["ANTIBOT_TIME_RESOLVE"]))
then
self.session_data = {}
- self.session_updated = true
- return
+ self:set_session_data()
+ return "need new prepare"
end
+ return "valid"
end
function antibot:set_session_data()
- if self.session_updated then
- local ok, err = set_session_data(self.session, self.session_data, true, self.ctx)
- if not ok then
- return false, err
- end
- self.session_updated = false
- return true, "updated"
- end
- return true, "no update"
+ self.session:set("antibot", self.session_data)
+ self.ctx.bw.antibot_session_data = self.session_data
+ self.ctx.bw.sessions_updated = true
end
function antibot:prepare_challenge()
if not self.session_data.prepared then
- self.session_updated = true
self.session_data.prepared = true
self.session_data.time_resolve = ngx.now()
self.session_data.type = self.variables["USE_ANTIBOT"]
@@ -283,6 +254,7 @@ function antibot:prepare_challenge()
elseif self.session_data.type == "captcha" then
self.session_data.captcha = rand(6, true)
end
+ self:set_session_data()
end
end
@@ -363,6 +335,7 @@ function antibot:check_challenge()
end
self.session_data.resolved = true
self.session_data.time_valid = now()
+ self:set_session_data()
return true, "resolved", self.session_data.original_uri
end
@@ -374,10 +347,11 @@ function antibot:check_challenge()
return nil, "missing challenge arg", nil
end
if self.session_data.captcha ~= args["captcha"] then
- return false, "wrong value", nil
+ return false, "wrong value, expected " .. self.session_data.captcha, nil
end
self.session_data.resolved = true
self.session_data.time_valid = now()
+ self:set_session_data()
return true, "resolved", self.session_data.original_uri
end
@@ -417,6 +391,7 @@ function antibot:check_challenge()
end
self.session_data.resolved = true
self.session_data.time_valid = now()
+ self:set_session_data()
return true, "resolved", self.session_data.original_uri
end
@@ -456,6 +431,7 @@ function antibot:check_challenge()
end
self.session_data.resolved = true
self.session_data.time_valid = now()
+ self:set_session_data()
return true, "resolved", self.session_data.original_uri
end
@@ -495,6 +471,7 @@ function antibot:check_challenge()
end
self.session_data.resolved = true
self.session_data.time_valid = now()
+ self:set_session_data()
return true, "resolved", self.session_data.original_uri
end
diff --git a/src/common/core/antibot/files/captcha.html b/src/common/core/antibot/files/captcha.html
index c43054dc6..dd49f3949 100644
--- a/src/common/core/antibot/files/captcha.html
+++ b/src/common/core/antibot/files/captcha.html
@@ -250,6 +250,7 @@
class="mt-3 px-2 text-gray-800 h-8 w-full max-w-[300px] rounded-lg outline-secondary"
type="text"
name="captcha"
+ required
/>
(mariadb|mysql)(\+pymysql)?|sqlite(\+pysqlite)?|postgresql):/+(?P/[^\s]+)")
+ DB_STRING_RX = re_compile(r"^(?P(mariadb|mysql)(\+pymysql)?|sqlite(\+pysqlite)?|postgresql(\+psycopg)?):/+(?P/[^\s]+)")
def __init__(
self,
@@ -85,6 +85,10 @@ class Database:
sleep(1)
else:
db_path.parent.mkdir(parents=True, exist_ok=True)
+ elif match.group("database").startswith("m") and not match.group("database").endswith("+pymysql"):
+ sqlalchemy_string = sqlalchemy_string.replace(match.group("database"), f"{match.group('database')}+pymysql") # ? This is mandatory for alemic to work with mariadb and mysql
+ elif match.group("database").startswith("postgresql") and not match.group("database").endswith("+psycopg"):
+ sqlalchemy_string = sqlalchemy_string.replace(match.group("database"), f"{match.group('database')}+psycopg") # ? This is strongly recommended as psycopg is the new way to connect to postgresql
self.database_uri = sqlalchemy_string
error = False
@@ -1039,10 +1043,10 @@ class Database:
return ""
- def delete_job_cache(self, file_name: str, *, job_name: Optional[str] = None):
+ def delete_job_cache(self, file_name: str, *, job_name: Optional[str] = None, service_id: Optional[str] = None):
job_name = job_name or basename(getsourcefile(_getframe(1))).replace(".py", "")
with self.__db_session() as session:
- session.query(Jobs_cache).filter_by(job_name=job_name, file_name=file_name).delete()
+ session.query(Jobs_cache).filter_by(job_name=job_name, file_name=file_name, service_id=service_id).delete()
def update_job_cache(
self,
diff --git a/src/common/db/requirements.in b/src/common/db/requirements.in
index d1975bf13..485e404cd 100644
--- a/src/common/db/requirements.in
+++ b/src/common/db/requirements.in
@@ -1,4 +1,4 @@
-cryptography==41.0.7
-psycopg2-binary==2.9.9
+cryptography==42.0.0
+psycopg[binary,pool]==3.1.17
PyMySQL==1.1.0
sqlalchemy==2.0.25
diff --git a/src/common/db/requirements.txt b/src/common/db/requirements.txt
index 38958f334..3d1fb8c84 100644
--- a/src/common/db/requirements.txt
+++ b/src/common/db/requirements.txt
@@ -58,30 +58,39 @@ cffi==1.16.0 \
--hash=sha256:fa3a0128b152627161ce47201262d3140edb5a5c3da88d73a1b790a959126956 \
--hash=sha256:fcc8eb6d5902bb1cf6dc4f187ee3ea80a1eba0a89aba40a5cb20a5087d961357
# via cryptography
-cryptography==41.0.7 \
- --hash=sha256:079b85658ea2f59c4f43b70f8119a52414cdb7be34da5d019a77bf96d473b960 \
- --hash=sha256:09616eeaef406f99046553b8a40fbf8b1e70795a91885ba4c96a70793de5504a \
- --hash=sha256:13f93ce9bea8016c253b34afc6bd6a75993e5c40672ed5405a9c832f0d4a00bc \
- --hash=sha256:37a138589b12069efb424220bf78eac59ca68b95696fc622b6ccc1c0a197204a \
- --hash=sha256:3c78451b78313fa81607fa1b3f1ae0a5ddd8014c38a02d9db0616133987b9cdf \
- --hash=sha256:43f2552a2378b44869fe8827aa19e69512e3245a219104438692385b0ee119d1 \
- --hash=sha256:48a0476626da912a44cc078f9893f292f0b3e4c739caf289268168d8f4702a39 \
- --hash=sha256:49f0805fc0b2ac8d4882dd52f4a3b935b210935d500b6b805f321addc8177406 \
- --hash=sha256:5429ec739a29df2e29e15d082f1d9ad683701f0ec7709ca479b3ff2708dae65a \
- --hash=sha256:5a1b41bc97f1ad230a41657d9155113c7521953869ae57ac39ac7f1bb471469a \
- --hash=sha256:68a2dec79deebc5d26d617bfdf6e8aab065a4f34934b22d3b5010df3ba36612c \
- --hash=sha256:7a698cb1dac82c35fcf8fe3417a3aaba97de16a01ac914b89a0889d364d2f6be \
- --hash=sha256:841df4caa01008bad253bce2a6f7b47f86dc9f08df4b433c404def869f590a15 \
- --hash=sha256:90452ba79b8788fa380dfb587cca692976ef4e757b194b093d845e8d99f612f2 \
- --hash=sha256:928258ba5d6f8ae644e764d0f996d61a8777559f72dfeb2eea7e2fe0ad6e782d \
- --hash=sha256:af03b32695b24d85a75d40e1ba39ffe7db7ffcb099fe507b39fd41a565f1b157 \
- --hash=sha256:b640981bf64a3e978a56167594a0e97db71c89a479da8e175d8bb5be5178c003 \
- --hash=sha256:c5ca78485a255e03c32b513f8c2bc39fedb7f5c5f8535545bdc223a03b24f248 \
- --hash=sha256:c7f3201ec47d5207841402594f1d7950879ef890c0c495052fa62f58283fde1a \
- --hash=sha256:d5ec85080cce7b0513cfd233914eb8b7bbd0633f1d1703aa28d1dd5a72f678ec \
- --hash=sha256:d6c391c021ab1f7a82da5d8d0b3cee2f4b2c455ec86c8aebbc84837a631ff309 \
- --hash=sha256:e3114da6d7f95d2dee7d3f4eec16dacff819740bbab931aff8648cb13c5ff5e7 \
- --hash=sha256:f983596065a18a2183e7f79ab3fd4c475205b839e02cbc0efbbf9666c4b3083d
+cryptography==42.0.0 \
+ --hash=sha256:0a68bfcf57a6887818307600c3c0ebc3f62fbb6ccad2240aa21887cda1f8df1b \
+ --hash=sha256:146e971e92a6dd042214b537a726c9750496128453146ab0ee8971a0299dc9bd \
+ --hash=sha256:14e4b909373bc5bf1095311fa0f7fcabf2d1a160ca13f1e9e467be1ac4cbdf94 \
+ --hash=sha256:206aaf42e031b93f86ad60f9f5d9da1b09164f25488238ac1dc488334eb5e221 \
+ --hash=sha256:3005166a39b70c8b94455fdbe78d87a444da31ff70de3331cdec2c568cf25b7e \
+ --hash=sha256:324721d93b998cb7367f1e6897370644751e5580ff9b370c0a50dc60a2003513 \
+ --hash=sha256:33588310b5c886dfb87dba5f013b8d27df7ffd31dc753775342a1e5ab139e59d \
+ --hash=sha256:35cf6ed4c38f054478a9df14f03c1169bb14bd98f0b1705751079b25e1cb58bc \
+ --hash=sha256:3ca482ea80626048975360c8e62be3ceb0f11803180b73163acd24bf014133a0 \
+ --hash=sha256:56ce0c106d5c3fec1038c3cca3d55ac320a5be1b44bf15116732d0bc716979a2 \
+ --hash=sha256:5a217bca51f3b91971400890905a9323ad805838ca3fa1e202a01844f485ee87 \
+ --hash=sha256:678cfa0d1e72ef41d48993a7be75a76b0725d29b820ff3cfd606a5b2b33fda01 \
+ --hash=sha256:69fd009a325cad6fbfd5b04c711a4da563c6c4854fc4c9544bff3088387c77c0 \
+ --hash=sha256:6cf9b76d6e93c62114bd19485e5cb003115c134cf9ce91f8ac924c44f8c8c3f4 \
+ --hash=sha256:74f18a4c8ca04134d2052a140322002fef535c99cdbc2a6afc18a8024d5c9d5b \
+ --hash=sha256:85f759ed59ffd1d0baad296e72780aa62ff8a71f94dc1ab340386a1207d0ea81 \
+ --hash=sha256:87086eae86a700307b544625e3ba11cc600c3c0ef8ab97b0fda0705d6db3d4e3 \
+ --hash=sha256:8814722cffcfd1fbd91edd9f3451b88a8f26a5fd41b28c1c9193949d1c689dc4 \
+ --hash=sha256:8fedec73d590fd30c4e3f0d0f4bc961aeca8390c72f3eaa1a0874d180e868ddf \
+ --hash=sha256:9515ea7f596c8092fdc9902627e51b23a75daa2c7815ed5aa8cf4f07469212ec \
+ --hash=sha256:988b738f56c665366b1e4bfd9045c3efae89ee366ca3839cd5af53eaa1401bce \
+ --hash=sha256:a2a8d873667e4fd2f34aedab02ba500b824692c6542e017075a2efc38f60a4c0 \
+ --hash=sha256:bd7cf7a8d9f34cc67220f1195884151426ce616fdc8285df9054bfa10135925f \
+ --hash=sha256:bdce70e562c69bb089523e75ef1d9625b7417c6297a76ac27b1b8b1eb51b7d0f \
+ --hash=sha256:be14b31eb3a293fc6e6aa2807c8a3224c71426f7c4e3639ccf1a2f3ffd6df8c3 \
+ --hash=sha256:be41b0c7366e5549265adf2145135dca107718fa44b6e418dc7499cfff6b4689 \
+ --hash=sha256:c310767268d88803b653fffe6d6f2f17bb9d49ffceb8d70aed50ad45ea49ab08 \
+ --hash=sha256:c58115384bdcfe9c7f644c72f10f6f42bed7cf59f7b52fe1bf7ae0a622b3a139 \
+ --hash=sha256:c640b0ef54138fde761ec99a6c7dc4ce05e80420262c20fa239e694ca371d434 \
+ --hash=sha256:ca20550bb590db16223eb9ccc5852335b48b8f597e2f6f0878bbfd9e7314eb17 \
+ --hash=sha256:d97aae66b7de41cdf5b12087b5509e4e9805ed6f562406dfcf60e8481a9a28f8 \
+ --hash=sha256:e9326ca78111e4c645f7e49cbce4ed2f3f85e17b61a563328c85a5208cf34440
# via -r requirements.in
greenlet==3.0.3 \
--hash=sha256:01bc7ea167cf943b4c802068e178bbf70ae2e8c080467070d01bfa02f337ee67 \
@@ -143,80 +152,83 @@ greenlet==3.0.3 \
--hash=sha256:fd096eb7ffef17c456cfa587523c5f92321ae02427ff955bebe9e3c63bc9f0da \
--hash=sha256:fe754d231288e1e64323cfad462fcee8f0288654c10bdf4f603a39ed923bef33
# via sqlalchemy
-psycopg2-binary==2.9.9 \
- --hash=sha256:03ef7df18daf2c4c07e2695e8cfd5ee7f748a1d54d802330985a78d2a5a6dca9 \
- --hash=sha256:0a602ea5aff39bb9fac6308e9c9d82b9a35c2bf288e184a816002c9fae930b77 \
- --hash=sha256:0c009475ee389757e6e34611d75f6e4f05f0cf5ebb76c6037508318e1a1e0d7e \
- --hash=sha256:0ef4854e82c09e84cc63084a9e4ccd6d9b154f1dbdd283efb92ecd0b5e2b8c84 \
- --hash=sha256:1236ed0952fbd919c100bc839eaa4a39ebc397ed1c08a97fc45fee2a595aa1b3 \
- --hash=sha256:143072318f793f53819048fdfe30c321890af0c3ec7cb1dfc9cc87aa88241de2 \
- --hash=sha256:15208be1c50b99203fe88d15695f22a5bed95ab3f84354c494bcb1d08557df67 \
- --hash=sha256:1873aade94b74715be2246321c8650cabf5a0d098a95bab81145ffffa4c13876 \
- --hash=sha256:18d0ef97766055fec15b5de2c06dd8e7654705ce3e5e5eed3b6651a1d2a9a152 \
- --hash=sha256:1ea665f8ce695bcc37a90ee52de7a7980be5161375d42a0b6c6abedbf0d81f0f \
- --hash=sha256:2293b001e319ab0d869d660a704942c9e2cce19745262a8aba2115ef41a0a42a \
- --hash=sha256:246b123cc54bb5361588acc54218c8c9fb73068bf227a4a531d8ed56fa3ca7d6 \
- --hash=sha256:275ff571376626195ab95a746e6a04c7df8ea34638b99fc11160de91f2fef503 \
- --hash=sha256:281309265596e388ef483250db3640e5f414168c5a67e9c665cafce9492eda2f \
- --hash=sha256:2d423c8d8a3c82d08fe8af900ad5b613ce3632a1249fd6a223941d0735fce493 \
- --hash=sha256:2e5afae772c00980525f6d6ecf7cbca55676296b580c0e6abb407f15f3706996 \
- --hash=sha256:30dcc86377618a4c8f3b72418df92e77be4254d8f89f14b8e8f57d6d43603c0f \
- --hash=sha256:31a34c508c003a4347d389a9e6fcc2307cc2150eb516462a7a17512130de109e \
- --hash=sha256:323ba25b92454adb36fa425dc5cf6f8f19f78948cbad2e7bc6cdf7b0d7982e59 \
- --hash=sha256:34eccd14566f8fe14b2b95bb13b11572f7c7d5c36da61caf414d23b91fcc5d94 \
- --hash=sha256:3a58c98a7e9c021f357348867f537017057c2ed7f77337fd914d0bedb35dace7 \
- --hash=sha256:3f78fd71c4f43a13d342be74ebbc0666fe1f555b8837eb113cb7416856c79682 \
- --hash=sha256:4154ad09dac630a0f13f37b583eae260c6aa885d67dfbccb5b02c33f31a6d420 \
- --hash=sha256:420f9bbf47a02616e8554e825208cb947969451978dceb77f95ad09c37791dae \
- --hash=sha256:4686818798f9194d03c9129a4d9a702d9e113a89cb03bffe08c6cf799e053291 \
- --hash=sha256:57fede879f08d23c85140a360c6a77709113efd1c993923c59fde17aa27599fe \
- --hash=sha256:60989127da422b74a04345096c10d416c2b41bd7bf2a380eb541059e4e999980 \
- --hash=sha256:64cf30263844fa208851ebb13b0732ce674d8ec6a0c86a4e160495d299ba3c93 \
- --hash=sha256:68fc1f1ba168724771e38bee37d940d2865cb0f562380a1fb1ffb428b75cb692 \
- --hash=sha256:6e6f98446430fdf41bd36d4faa6cb409f5140c1c2cf58ce0bbdaf16af7d3f119 \
- --hash=sha256:729177eaf0aefca0994ce4cffe96ad3c75e377c7b6f4efa59ebf003b6d398716 \
- --hash=sha256:72dffbd8b4194858d0941062a9766f8297e8868e1dd07a7b36212aaa90f49472 \
- --hash=sha256:75723c3c0fbbf34350b46a3199eb50638ab22a0228f93fb472ef4d9becc2382b \
- --hash=sha256:77853062a2c45be16fd6b8d6de2a99278ee1d985a7bd8b103e97e41c034006d2 \
- --hash=sha256:78151aa3ec21dccd5cdef6c74c3e73386dcdfaf19bced944169697d7ac7482fc \
- --hash=sha256:7f01846810177d829c7692f1f5ada8096762d9172af1b1a28d4ab5b77c923c1c \
- --hash=sha256:804d99b24ad523a1fe18cc707bf741670332f7c7412e9d49cb5eab67e886b9b5 \
- --hash=sha256:81ff62668af011f9a48787564ab7eded4e9fb17a4a6a74af5ffa6a457400d2ab \
- --hash=sha256:8359bf4791968c5a78c56103702000105501adb557f3cf772b2c207284273984 \
- --hash=sha256:83791a65b51ad6ee6cf0845634859d69a038ea9b03d7b26e703f94c7e93dbcf9 \
- --hash=sha256:8532fd6e6e2dc57bcb3bc90b079c60de896d2128c5d9d6f24a63875a95a088cf \
- --hash=sha256:876801744b0dee379e4e3c38b76fc89f88834bb15bf92ee07d94acd06ec890a0 \
- --hash=sha256:8dbf6d1bc73f1d04ec1734bae3b4fb0ee3cb2a493d35ede9badbeb901fb40f6f \
- --hash=sha256:8f8544b092a29a6ddd72f3556a9fcf249ec412e10ad28be6a0c0d948924f2212 \
- --hash=sha256:911dda9c487075abd54e644ccdf5e5c16773470a6a5d3826fda76699410066fb \
- --hash=sha256:977646e05232579d2e7b9c59e21dbe5261f403a88417f6a6512e70d3f8a046be \
- --hash=sha256:9dba73be7305b399924709b91682299794887cbbd88e38226ed9f6712eabee90 \
- --hash=sha256:a148c5d507bb9b4f2030a2025c545fccb0e1ef317393eaba42e7eabd28eb6041 \
- --hash=sha256:a6cdcc3ede532f4a4b96000b6362099591ab4a3e913d70bcbac2b56c872446f7 \
- --hash=sha256:ac05fb791acf5e1a3e39402641827780fe44d27e72567a000412c648a85ba860 \
- --hash=sha256:b0605eaed3eb239e87df0d5e3c6489daae3f7388d455d0c0b4df899519c6a38d \
- --hash=sha256:b58b4710c7f4161b5e9dcbe73bb7c62d65670a87df7bcce9e1faaad43e715245 \
- --hash=sha256:b6356793b84728d9d50ead16ab43c187673831e9d4019013f1402c41b1db9b27 \
- --hash=sha256:b76bedd166805480ab069612119ea636f5ab8f8771e640ae103e05a4aae3e417 \
- --hash=sha256:bc7bb56d04601d443f24094e9e31ae6deec9ccb23581f75343feebaf30423359 \
- --hash=sha256:c2470da5418b76232f02a2fcd2229537bb2d5a7096674ce61859c3229f2eb202 \
- --hash=sha256:c332c8d69fb64979ebf76613c66b985414927a40f8defa16cf1bc028b7b0a7b0 \
- --hash=sha256:c6af2a6d4b7ee9615cbb162b0738f6e1fd1f5c3eda7e5da17861eacf4c717ea7 \
- --hash=sha256:c77e3d1862452565875eb31bdb45ac62502feabbd53429fdc39a1cc341d681ba \
- --hash=sha256:ca08decd2697fdea0aea364b370b1249d47336aec935f87b8bbfd7da5b2ee9c1 \
- --hash=sha256:ca49a8119c6cbd77375ae303b0cfd8c11f011abbbd64601167ecca18a87e7cdd \
- --hash=sha256:cb16c65dcb648d0a43a2521f2f0a2300f40639f6f8c1ecbc662141e4e3e1ee07 \
- --hash=sha256:d2997c458c690ec2bc6b0b7ecbafd02b029b7b4283078d3b32a852a7ce3ddd98 \
- --hash=sha256:d3f82c171b4ccd83bbaf35aa05e44e690113bd4f3b7b6cc54d2219b132f3ae55 \
- --hash=sha256:dc4926288b2a3e9fd7b50dc6a1909a13bbdadfc67d93f3374d984e56f885579d \
- --hash=sha256:ead20f7913a9c1e894aebe47cccf9dc834e1618b7aa96155d2091a626e59c972 \
- --hash=sha256:ebdc36bea43063116f0486869652cb2ed7032dbc59fbcb4445c4862b5c1ecf7f \
- --hash=sha256:ed1184ab8f113e8d660ce49a56390ca181f2981066acc27cf637d5c1e10ce46e \
- --hash=sha256:ee825e70b1a209475622f7f7b776785bd68f34af6e7a46e2e42f27b659b5bc26 \
- --hash=sha256:f7ae5d65ccfbebdfa761585228eb4d0df3a8b15cfb53bd953e713e09fbb12957 \
- --hash=sha256:f7fc5a5acafb7d6ccca13bfa8c90f8c51f13d8fb87d95656d3950f0158d3ce53 \
- --hash=sha256:f9b5571d33660d5009a8b3c25dc1db560206e2d2f89d3df1cb32d72c0d117d52
- # via -r requirements.in
+psycopg==3.1.17 \
+ --hash=sha256:437e7d7925459f21de570383e2e10542aceb3b9cb972ce957fdd3826ca47edc6 \
+ --hash=sha256:96b7b13af6d5a514118b759a66b2799a8a4aa78675fa6bb0d3f7d52d67eff002
+ # via
+ # -r requirements.in
+ # psycopg
+psycopg-binary==3.1.17 \
+ --hash=sha256:00377f6963ee7e4bf71cab17c2c235ef0624df9483f3b615d86aa24cde889d42 \
+ --hash=sha256:0227885686c2cc0104ceb22d6eebc732766e9ad48710408cb0123237432e5435 \
+ --hash=sha256:02ac573f5a6e79bb6df512b3a6279f01f033bbd45c47186e8872fee45f6681d0 \
+ --hash=sha256:02cd2eb62ffc56f8c847d68765cbf461b3d11b438fe48951e44b6c563ec27d18 \
+ --hash=sha256:0340ef87a888fd940796c909e038426f4901046f61856598582a817162c64984 \
+ --hash=sha256:0b1ec6895cab887b92c303565617f994c9b9db53befda81fa2a31b76fe8a3ab1 \
+ --hash=sha256:12eab8bc91b4ba01b2ecee3b5b80501934b198f6e1f8d4b13596f3f38ba6e762 \
+ --hash=sha256:267a82548c21476120e43dc72b961f1af52c380c0b4c951bdb34cf14cb26bd35 \
+ --hash=sha256:2a05400e9314fc30bc1364865ba9f6eaa2def42b5e7e67f71f9a4430f870023e \
+ --hash=sha256:2b2a689eaede08cf91a36b10b0da6568dd6e4669200f201e082639816737992b \
+ --hash=sha256:3d0d154c780cc7b28a3a0886e8a4b18689202a1dbb522b3c771eb3a1289cf7c3 \
+ --hash=sha256:3e2cc2bbf37ff1cf11e8b871c294e3532636a3cf7f0c82518b7537158923d77b \
+ --hash=sha256:40af298b209dd77ca2f3e7eb3fbcfb87a25999fc015fcd14140bde030a164c7e \
+ --hash=sha256:420c1eb1626539c261cf3fbe099998da73eb990f9ce1a34da7feda414012ea5f \
+ --hash=sha256:4b20013051f1fd7d02b8d0766cfe8d009e8078babc00a6d39bc7e2d50a7b96af \
+ --hash=sha256:4fa26836ce074a1104249378727e1f239a01530f36bae16e77cf6c50968599b4 \
+ --hash=sha256:5ccbe8b2ec444763a51ecb1213befcbb75defc1ef36e7dd5dff501a23d7ce8cf \
+ --hash=sha256:5f5f5bcbb772d8c243d605fc7151beec760dd27532d42145a58fb74ef9c5fbf2 \
+ --hash=sha256:61104b8e7a43babf2bbaa36c08e31a12023e2f967166e99d6b052b11a4c7db06 \
+ --hash=sha256:67a5b93101bc85a95a189c0a23d02a29cf06c1080a695a0dedfdd50dd734662a \
+ --hash=sha256:6a728beefd89b430ebe2729d04ba10e05036b5e9d01648da60436000d2fcd242 \
+ --hash=sha256:6b2ae342d69684555bfe77aed5546d125b4a99012e0b83a8b3da68c8829f0935 \
+ --hash=sha256:6b40fa54a02825d3d6a8009d9a82a2b4fad80387acf2b8fd6d398fd2813cb2d9 \
+ --hash=sha256:6d4f2e15d33ed4f9776fdf23683512d76f4e7825c4b80677e9e3ce6c1b193ff2 \
+ --hash=sha256:6e3543edc18553e31a3884af3cd7eea43d6c44532d8b9b16f3e743cdf6cfe6c5 \
+ --hash=sha256:704f6393d758b12a4369887fe956b2a8c99e4aced839d9084de8e3f056015d40 \
+ --hash=sha256:73e7097b81cad9ae358334e3cec625246bb3b8013ae6bb287758dd6435e12f65 \
+ --hash=sha256:751b31c2faae0348f87f22b45ef58f704bdcfc2abdd680fa0c743c124071157e \
+ --hash=sha256:78ebb43dca7d5b41eee543cd005ee5a0256cecc74d84acf0fab4f025997b837e \
+ --hash=sha256:7b4e4c2b05f3b431e9026e82590b217e87696e7a7548f512ae8059d59fa8af3b \
+ --hash=sha256:7e28024204dc0c61094268c682041d2becfedfea2e3b46bed5f6138239304d98 \
+ --hash=sha256:83404a353240fdff5cfe9080665fdfdcaa2d4d0c5112e15b0a2fe2e59200ed57 \
+ --hash=sha256:86bb3656c8d744cc1e42003414cd6c765117d70aa23da6c0f4ff2b826e0fd0fd \
+ --hash=sha256:8c5c38129cc79d7e3ba553035b9962a442171e9f97bb1b8795c0885213f206f3 \
+ --hash=sha256:9124b6db07e8d8b11f4512b8b56cbe136bf1b7d0417d1280e62291a9dcad4408 \
+ --hash=sha256:914254849486e14aa931b0b3382cd16887f1507068ffba775cbdc5a55fe9ef19 \
+ --hash=sha256:92fad8f1aa80a5ab316c0493dc6d1b54c1dba21937e43eea7296ff4a0ccc071e \
+ --hash=sha256:93921178b9a40c60c26e47eb44970f88c49fe484aaa3bb7ec02bb8b514eab3d9 \
+ --hash=sha256:9690a535d9ccd361bbc3590bfce7fe679e847f44fa7cc97f3b885f4744ca8a2c \
+ --hash=sha256:a0c4ba73f9e7721dd6cc3e6953016652dbac206f654229b7a1a8ac182b16e689 \
+ --hash=sha256:a16abab0c1abc58feb6ab11d78d0f8178a67c3586bd70628ec7c0218ec04c4ef \
+ --hash=sha256:a343261701a8f63f0d8268f7fd32be40ffe28d24b65d905404ca03e7281f7bb5 \
+ --hash=sha256:a3f1196d76860e72d338fab0d2b6722e8d47e2285d693e366ae36011c4a5898a \
+ --hash=sha256:a880e4113af3ab84d6a0991e3f85a2424924c8a182733ab8d964421df8b5190a \
+ --hash=sha256:a89f36bf7b612ff6ed3e789bd987cbd0787cf0d66c49386fa3bad816dd7bee87 \
+ --hash=sha256:adb670031b27949c9dc5cf585c4a5a6b4469d3879fd2fb9d39b6d53e5f66b9bc \
+ --hash=sha256:b0711e46361ea3047cd049868419d030c8236a9dea7e9ed1f053cbd61a853ec9 \
+ --hash=sha256:b447ea765e71bc33a82cf070bba814b1efa77967442d116b95ccef8ce5da7631 \
+ --hash=sha256:bf424d92dd7e94705b31625b02d396297a7c8fab4b6f7de8dba6388323a7b71c \
+ --hash=sha256:c10b7713e3ed31df7319c2a72d5fea5a2536476d7695a3e1d18a1f289060997c \
+ --hash=sha256:c8a46f77ba0ca7c5a5449b777170a518fa7820e1710edb40e777c9798f00d033 \
+ --hash=sha256:ca1757a6e080086f7234dc45684e81a47a66a6dd492a37d6ce38c58a1a93e9ff \
+ --hash=sha256:d01c4faae66de60fcd3afd3720dcc8ffa03bc2087f898106da127774db12aac5 \
+ --hash=sha256:d1c0115bdf80cf6c8c9109cb10cf6f650fd1a8d841f884925e8cb12f34eb5371 \
+ --hash=sha256:d2e9ed88d9a6a475c67bf70fc8285e88ccece0391727c7701e5a512e0eafbb05 \
+ --hash=sha256:d54bcf2dfc0880bf13f38512d44b194c092794e4ee9e01d804bc6cd3eed9bfb7 \
+ --hash=sha256:d613a23f8928f30acb2b6b2398cb7775ba9852e8968e15df13807ba0d3ebd565 \
+ --hash=sha256:d90c0531e9d591bde8cea04e75107fcddcc56811b638a34853436b23c9a3cb7d \
+ --hash=sha256:dceb3930ec426623c0cacc78e447a90882981e8c49d6fea8d1e48850e24a0170 \
+ --hash=sha256:e1e867c2a729348df218a14ba1b862e627177fd57c7b4f3db0b4c708f6d03696 \
+ --hash=sha256:e6ae27b0617ad3809449964b5e901b21acff8e306abacb8ba71d5ee7c8c47eeb \
+ --hash=sha256:ea425a8dcd808a7232a5417d2633bfa543da583a2701b5228e9e29989a50deda \
+ --hash=sha256:f4028443bf25c1e04ecffdc552c0a98d826903dec76a1568dfddf5ebbbb03db7 \
+ --hash=sha256:f6898bf1ca5aa01115807643138e3e20ec603b17a811026bc4a49d43055720a7 \
+ --hash=sha256:f9ba559eabb0ba1afd4e0504fa0b10e00a212cac0c4028b8a1c3b087b5c1e5de
+ # via psycopg
+psycopg-pool==3.2.1 \
+ --hash=sha256:060b551d1b97a8d358c668be58b637780b884de14d861f4f5ecc48b7563aafb7 \
+ --hash=sha256:6509a75c073590952915eddbba7ce8b8332a440a31e77bba69561483492829ad
+ # via psycopg
pycparser==2.21 \
--hash=sha256:8ee45429555515e1f6b185e78100aea234072576aa43ab53aefcae078162fca9 \
--hash=sha256:e644fdec12f7872f86c58ff790da456218b10f863970249516d60a5eaca77206
@@ -279,4 +291,7 @@ sqlalchemy==2.0.25 \
typing-extensions==4.9.0 \
--hash=sha256:23478f88c37f27d76ac8aee6c905017a143b0b1b886c3c9f66bc2fd94f9f5783 \
--hash=sha256:af72aea155e91adfc61c3ae9e0e342dbc0cba726d6cba4b6c72c1f34e47291cd
- # via sqlalchemy
+ # via
+ # psycopg
+ # psycopg-pool
+ # sqlalchemy
diff --git a/src/common/gen/requirements.in b/src/common/gen/requirements.in
index 406f51f15..0b5e9869c 100644
--- a/src/common/gen/requirements.in
+++ b/src/common/gen/requirements.in
@@ -1,6 +1,5 @@
docker==7.0.0
jinja2==3.1.3
kubernetes==29.0.0
-python-dotenv==1.0.0
+python-dotenv==1.0.1
redis==5.0.1
-urllib3<2.0.0
diff --git a/src/common/gen/requirements.txt b/src/common/gen/requirements.txt
index 685a0975e..b4c8827cf 100644
--- a/src/common/gen/requirements.txt
+++ b/src/common/gen/requirements.txt
@@ -130,67 +130,67 @@ kubernetes==29.0.0 \
--hash=sha256:ab8cb0e0576ccdfb71886366efb102c6a20f268d817be065ce7f9909c631e43e \
--hash=sha256:c4812e227ae74d07d53c88293e564e54b850452715a59a927e7e1bc6b9a60459
# via -r requirements.in
-markupsafe==2.1.3 \
- --hash=sha256:05fb21170423db021895e1ea1e1f3ab3adb85d1c2333cbc2310f2a26bc77272e \
- --hash=sha256:0a4e4a1aff6c7ac4cd55792abf96c915634c2b97e3cc1c7129578aa68ebd754e \
- --hash=sha256:10bbfe99883db80bdbaff2dcf681dfc6533a614f700da1287707e8a5d78a8431 \
- --hash=sha256:134da1eca9ec0ae528110ccc9e48041e0828d79f24121a1a146161103c76e686 \
- --hash=sha256:14ff806850827afd6b07a5f32bd917fb7f45b046ba40c57abdb636674a8b559c \
- --hash=sha256:1577735524cdad32f9f694208aa75e422adba74f1baee7551620e43a3141f559 \
- --hash=sha256:1b40069d487e7edb2676d3fbdb2b0829ffa2cd63a2ec26c4938b2d34391b4ecc \
- --hash=sha256:1b8dd8c3fd14349433c79fa8abeb573a55fc0fdd769133baac1f5e07abf54aeb \
- --hash=sha256:1f67c7038d560d92149c060157d623c542173016c4babc0c1913cca0564b9939 \
- --hash=sha256:282c2cb35b5b673bbcadb33a585408104df04f14b2d9b01d4c345a3b92861c2c \
- --hash=sha256:2c1b19b3aaacc6e57b7e25710ff571c24d6c3613a45e905b1fde04d691b98ee0 \
- --hash=sha256:2ef12179d3a291be237280175b542c07a36e7f60718296278d8593d21ca937d4 \
- --hash=sha256:338ae27d6b8745585f87218a3f23f1512dbf52c26c28e322dbe54bcede54ccb9 \
- --hash=sha256:3c0fae6c3be832a0a0473ac912810b2877c8cb9d76ca48de1ed31e1c68386575 \
- --hash=sha256:3fd4abcb888d15a94f32b75d8fd18ee162ca0c064f35b11134be77050296d6ba \
- --hash=sha256:42de32b22b6b804f42c5d98be4f7e5e977ecdd9ee9b660fda1a3edf03b11792d \
- --hash=sha256:47d4f1c5f80fc62fdd7777d0d40a2e9dda0a05883ab11374334f6c4de38adffd \
- --hash=sha256:504b320cd4b7eff6f968eddf81127112db685e81f7e36e75f9f84f0df46041c3 \
- --hash=sha256:525808b8019e36eb524b8c68acdd63a37e75714eac50e988180b169d64480a00 \
- --hash=sha256:56d9f2ecac662ca1611d183feb03a3fa4406469dafe241673d521dd5ae92a155 \
- --hash=sha256:5bbe06f8eeafd38e5d0a4894ffec89378b6c6a625ff57e3028921f8ff59318ac \
- --hash=sha256:65c1a9bcdadc6c28eecee2c119465aebff8f7a584dd719facdd9e825ec61ab52 \
- --hash=sha256:68e78619a61ecf91e76aa3e6e8e33fc4894a2bebe93410754bd28fce0a8a4f9f \
- --hash=sha256:69c0f17e9f5a7afdf2cc9fb2d1ce6aabdb3bafb7f38017c0b77862bcec2bbad8 \
- --hash=sha256:6b2b56950d93e41f33b4223ead100ea0fe11f8e6ee5f641eb753ce4b77a7042b \
- --hash=sha256:715d3562f79d540f251b99ebd6d8baa547118974341db04f5ad06d5ea3eb8007 \
- --hash=sha256:787003c0ddb00500e49a10f2844fac87aa6ce977b90b0feaaf9de23c22508b24 \
- --hash=sha256:7ef3cb2ebbf91e330e3bb937efada0edd9003683db6b57bb108c4001f37a02ea \
- --hash=sha256:8023faf4e01efadfa183e863fefde0046de576c6f14659e8782065bcece22198 \
- --hash=sha256:8758846a7e80910096950b67071243da3e5a20ed2546e6392603c096778d48e0 \
- --hash=sha256:8afafd99945ead6e075b973fefa56379c5b5c53fd8937dad92c662da5d8fd5ee \
- --hash=sha256:8c41976a29d078bb235fea9b2ecd3da465df42a562910f9022f1a03107bd02be \
- --hash=sha256:8e254ae696c88d98da6555f5ace2279cf7cd5b3f52be2b5cf97feafe883b58d2 \
- --hash=sha256:8f9293864fe09b8149f0cc42ce56e3f0e54de883a9de90cd427f191c346eb2e1 \
- --hash=sha256:9402b03f1a1b4dc4c19845e5c749e3ab82d5078d16a2a4c2cd2df62d57bb0707 \
- --hash=sha256:962f82a3086483f5e5f64dbad880d31038b698494799b097bc59c2edf392fce6 \
- --hash=sha256:9aad3c1755095ce347e26488214ef77e0485a3c34a50c5a5e2471dff60b9dd9c \
- --hash=sha256:9dcdfd0eaf283af041973bff14a2e143b8bd64e069f4c383416ecd79a81aab58 \
- --hash=sha256:aa57bd9cf8ae831a362185ee444e15a93ecb2e344c8e52e4d721ea3ab6ef1823 \
- --hash=sha256:aa7bd130efab1c280bed0f45501b7c8795f9fdbeb02e965371bbef3523627779 \
- --hash=sha256:ab4a0df41e7c16a1392727727e7998a467472d0ad65f3ad5e6e765015df08636 \
- --hash=sha256:ad9e82fb8f09ade1c3e1b996a6337afac2b8b9e365f926f5a61aacc71adc5b3c \
- --hash=sha256:af598ed32d6ae86f1b747b82783958b1a4ab8f617b06fe68795c7f026abbdcad \
- --hash=sha256:b076b6226fb84157e3f7c971a47ff3a679d837cf338547532ab866c57930dbee \
- --hash=sha256:b7ff0f54cb4ff66dd38bebd335a38e2c22c41a8ee45aa608efc890ac3e3931bc \
- --hash=sha256:bfce63a9e7834b12b87c64d6b155fdd9b3b96191b6bd334bf37db7ff1fe457f2 \
- --hash=sha256:c011a4149cfbcf9f03994ec2edffcb8b1dc2d2aede7ca243746df97a5d41ce48 \
- --hash=sha256:c9c804664ebe8f83a211cace637506669e7890fec1b4195b505c214e50dd4eb7 \
- --hash=sha256:ca379055a47383d02a5400cb0d110cef0a776fc644cda797db0c5696cfd7e18e \
- --hash=sha256:cb0932dc158471523c9637e807d9bfb93e06a95cbf010f1a38b98623b929ef2b \
- --hash=sha256:cd0f502fe016460680cd20aaa5a76d241d6f35a1c3350c474bac1273803893fa \
- --hash=sha256:ceb01949af7121f9fc39f7d27f91be8546f3fb112c608bc4029aef0bab86a2a5 \
- --hash=sha256:d080e0a5eb2529460b30190fcfcc4199bd7f827663f858a226a81bc27beaa97e \
- --hash=sha256:dd15ff04ffd7e05ffcb7fe79f1b98041b8ea30ae9234aed2a9168b5797c3effb \
- --hash=sha256:df0be2b576a7abbf737b1575f048c23fb1d769f267ec4358296f31c2479db8f9 \
- --hash=sha256:e09031c87a1e51556fdcb46e5bd4f59dfb743061cf93c4d6831bf894f125eb57 \
- --hash=sha256:e4dd52d80b8c83fdce44e12478ad2e85c64ea965e75d66dbeafb0a3e77308fcc \
- --hash=sha256:f698de3fd0c4e6972b92290a45bd9b1536bffe8c6759c62471efaa8acb4c37bc \
- --hash=sha256:fec21693218efe39aa7f8599346e90c705afa52c5b31ae019b2e57e8f6542bb2 \
- --hash=sha256:ffcc3f7c66b5f5b7931a5aa68fc9cecc51e685ef90282f4a82f0f5e9b704ad11
+markupsafe==2.1.4 \
+ --hash=sha256:0042d6a9880b38e1dd9ff83146cc3c9c18a059b9360ceae207805567aacccc69 \
+ --hash=sha256:0c26f67b3fe27302d3a412b85ef696792c4a2386293c53ba683a89562f9399b0 \
+ --hash=sha256:0fbad3d346df8f9d72622ac71b69565e621ada2ce6572f37c2eae8dacd60385d \
+ --hash=sha256:15866d7f2dc60cfdde12ebb4e75e41be862348b4728300c36cdf405e258415ec \
+ --hash=sha256:1c98c33ffe20e9a489145d97070a435ea0679fddaabcafe19982fe9c971987d5 \
+ --hash=sha256:21e7af8091007bf4bebf4521184f4880a6acab8df0df52ef9e513d8e5db23411 \
+ --hash=sha256:23984d1bdae01bee794267424af55eef4dfc038dc5d1272860669b2aa025c9e3 \
+ --hash=sha256:31f57d64c336b8ccb1966d156932f3daa4fee74176b0fdc48ef580be774aae74 \
+ --hash=sha256:3583a3a3ab7958e354dc1d25be74aee6228938312ee875a22330c4dc2e41beb0 \
+ --hash=sha256:36d7626a8cca4d34216875aee5a1d3d654bb3dac201c1c003d182283e3205949 \
+ --hash=sha256:396549cea79e8ca4ba65525470d534e8a41070e6b3500ce2414921099cb73e8d \
+ --hash=sha256:3a66c36a3864df95e4f62f9167c734b3b1192cb0851b43d7cc08040c074c6279 \
+ --hash=sha256:3aae9af4cac263007fd6309c64c6ab4506dd2b79382d9d19a1994f9240b8db4f \
+ --hash=sha256:3ab3a886a237f6e9c9f4f7d272067e712cdb4efa774bef494dccad08f39d8ae6 \
+ --hash=sha256:47bb5f0142b8b64ed1399b6b60f700a580335c8e1c57f2f15587bd072012decc \
+ --hash=sha256:49a3b78a5af63ec10d8604180380c13dcd870aba7928c1fe04e881d5c792dc4e \
+ --hash=sha256:4df98d4a9cd6a88d6a585852f56f2155c9cdb6aec78361a19f938810aa020954 \
+ --hash=sha256:5045e892cfdaecc5b4c01822f353cf2c8feb88a6ec1c0adef2a2e705eef0f656 \
+ --hash=sha256:5244324676254697fe5c181fc762284e2c5fceeb1c4e3e7f6aca2b6f107e60dc \
+ --hash=sha256:54635102ba3cf5da26eb6f96c4b8c53af8a9c0d97b64bdcb592596a6255d8518 \
+ --hash=sha256:54a7e1380dfece8847c71bf7e33da5d084e9b889c75eca19100ef98027bd9f56 \
+ --hash=sha256:55d03fea4c4e9fd0ad75dc2e7e2b6757b80c152c032ea1d1de487461d8140efc \
+ --hash=sha256:698e84142f3f884114ea8cf83e7a67ca8f4ace8454e78fe960646c6c91c63bfa \
+ --hash=sha256:6aa5e2e7fc9bc042ae82d8b79d795b9a62bd8f15ba1e7594e3db243f158b5565 \
+ --hash=sha256:7653fa39578957bc42e5ebc15cf4361d9e0ee4b702d7d5ec96cdac860953c5b4 \
+ --hash=sha256:765f036a3d00395a326df2835d8f86b637dbaf9832f90f5d196c3b8a7a5080cb \
+ --hash=sha256:78bc995e004681246e85e28e068111a4c3f35f34e6c62da1471e844ee1446250 \
+ --hash=sha256:7a07f40ef8f0fbc5ef1000d0c78771f4d5ca03b4953fc162749772916b298fc4 \
+ --hash=sha256:8b570a1537367b52396e53325769608f2a687ec9a4363647af1cded8928af959 \
+ --hash=sha256:987d13fe1d23e12a66ca2073b8d2e2a75cec2ecb8eab43ff5624ba0ad42764bc \
+ --hash=sha256:9896fca4a8eb246defc8b2a7ac77ef7553b638e04fbf170bff78a40fa8a91474 \
+ --hash=sha256:9e9e3c4020aa2dc62d5dd6743a69e399ce3de58320522948af6140ac959ab863 \
+ --hash=sha256:a0b838c37ba596fcbfca71651a104a611543077156cb0a26fe0c475e1f152ee8 \
+ --hash=sha256:a4d176cfdfde84f732c4a53109b293d05883e952bbba68b857ae446fa3119b4f \
+ --hash=sha256:a76055d5cb1c23485d7ddae533229039b850db711c554a12ea64a0fd8a0129e2 \
+ --hash=sha256:a76cd37d229fc385738bd1ce4cba2a121cf26b53864c1772694ad0ad348e509e \
+ --hash=sha256:a7cc49ef48a3c7a0005a949f3c04f8baa5409d3f663a1b36f0eba9bfe2a0396e \
+ --hash=sha256:abf5ebbec056817057bfafc0445916bb688a255a5146f900445d081db08cbabb \
+ --hash=sha256:b0fe73bac2fed83839dbdbe6da84ae2a31c11cfc1c777a40dbd8ac8a6ed1560f \
+ --hash=sha256:b6f14a9cd50c3cb100eb94b3273131c80d102e19bb20253ac7bd7336118a673a \
+ --hash=sha256:b83041cda633871572f0d3c41dddd5582ad7d22f65a72eacd8d3d6d00291df26 \
+ --hash=sha256:b835aba863195269ea358cecc21b400276747cc977492319fd7682b8cd2c253d \
+ --hash=sha256:bf1196dcc239e608605b716e7b166eb5faf4bc192f8a44b81e85251e62584bd2 \
+ --hash=sha256:c669391319973e49a7c6230c218a1e3044710bc1ce4c8e6eb71f7e6d43a2c131 \
+ --hash=sha256:c7556bafeaa0a50e2fe7dc86e0382dea349ebcad8f010d5a7dc6ba568eaaa789 \
+ --hash=sha256:c8f253a84dbd2c63c19590fa86a032ef3d8cc18923b8049d91bcdeeb2581fbf6 \
+ --hash=sha256:d18b66fe626ac412d96c2ab536306c736c66cf2a31c243a45025156cc190dc8a \
+ --hash=sha256:d5291d98cd3ad9a562883468c690a2a238c4a6388ab3bd155b0c75dd55ece858 \
+ --hash=sha256:d5c31fe855c77cad679b302aabc42d724ed87c043b1432d457f4976add1c2c3e \
+ --hash=sha256:d6e427c7378c7f1b2bef6a344c925b8b63623d3321c09a237b7cc0e77dd98ceb \
+ --hash=sha256:dac1ebf6983148b45b5fa48593950f90ed6d1d26300604f321c74a9ca1609f8e \
+ --hash=sha256:de8153a7aae3835484ac168a9a9bdaa0c5eee4e0bc595503c95d53b942879c84 \
+ --hash=sha256:e1a0d1924a5013d4f294087e00024ad25668234569289650929ab871231668e7 \
+ --hash=sha256:e7902211afd0af05fbadcc9a312e4cf10f27b779cf1323e78d52377ae4b72bea \
+ --hash=sha256:e888ff76ceb39601c59e219f281466c6d7e66bd375b4ec1ce83bcdc68306796b \
+ --hash=sha256:f06e5a9e99b7df44640767842f414ed5d7bedaaa78cd817ce04bbd6fd86e2dd6 \
+ --hash=sha256:f6be2d708a9d0e9b0054856f07ac7070fbe1754be40ca8525d5adccdbda8f475 \
+ --hash=sha256:f9917691f410a2e0897d1ef99619fd3f7dd503647c8ff2475bf90c3cf222ad74 \
+ --hash=sha256:fc1a75aa8f11b87910ffd98de62b29d6520b6d6e8a3de69a70ca34dea85d2a8a \
+ --hash=sha256:fe8512ed897d5daf089e5bd010c3dc03bb1bdae00b35588c49b98268d4a01e00
# via jinja2
oauthlib==3.2.2 \
--hash=sha256:8139f29aac13e25d502680e9e19963e83f16838d48a0d71c287fe40e7067fbca \
@@ -216,9 +216,9 @@ python-dateutil==2.8.2 \
--hash=sha256:0123cacc1627ae19ddf3c27a5de5bd67ee4586fbdd6440d9748f8abb483d3e86 \
--hash=sha256:961d03dc3453ebbc59dbdea9e4e11c5651520a876d0f4db161e8674aae935da9
# via kubernetes
-python-dotenv==1.0.0 \
- --hash=sha256:a8df96034aae6d2d50a4ebe8216326c61c3eb64836776504fcca410e5937a3ba \
- --hash=sha256:f5971a9226b701070a4bf2c38c89e5a3f0d64de8debda981d1db98583009122a
+python-dotenv==1.0.1 \
+ --hash=sha256:e324ee90a023d808f1959c46bcbc04446a10ced277783dc6ee09987c37ec10ca \
+ --hash=sha256:f7b63ef50f1b690dddf550d03497b66d609393b40b564ed0d674909a68ebf16a
# via -r requirements.in
pyyaml==6.0.1 \
--hash=sha256:04ac92ad1925b2cff1db0cfebffb6ffc43457495c9b3c39d3fcae417d7125dc5 \
@@ -250,6 +250,7 @@ pyyaml==6.0.1 \
--hash=sha256:8d4e9c88387b0f5c7d5f281e55304de64cf7f9c0021a3525bd3b1c542da3b0e4 \
--hash=sha256:9046c58c4395dff28dd494285c82ba00b546adfc7ef001486fbf0324bc174fba \
--hash=sha256:9eb6caa9a297fc2c2fb8862bc5370d0303ddba53ba97e71f08023b6cd73d16a8 \
+ --hash=sha256:a08c6f0fe150303c1c6b71ebcd7213c2858041a7e01975da3a99aed1e7a378ef \
--hash=sha256:a0cd17c15d3bb3fa06978b4e8958dcdc6e0174ccea823003a106c7d4d7899ac5 \
--hash=sha256:afd7e57eddb1a54f0f1a974bc4391af8bcce0b444685d936840f125cf046d5bd \
--hash=sha256:b1275ad35a5d18c62a7220633c913e1b42d44b46ee12554e5fd39c70a243d6a3 \
@@ -297,11 +298,10 @@ six==1.16.0 \
# via
# kubernetes
# python-dateutil
-urllib3==1.26.18 \
- --hash=sha256:34b97092d7e0a3a8cf7cd10e386f401b3737364026c45e622aa02903dffe0f07 \
- --hash=sha256:f8ecc1bba5667413457c529ab955bf8c67b45db799d159066261719e328580a0
+urllib3==2.1.0 \
+ --hash=sha256:55901e917a5896a349ff771be919f8bd99aff50b79fe58fec595eb37bbc56bb3 \
+ --hash=sha256:df7aa8afb0148fa78488e7899b2c59b5f4ffcfa82e6c54ccb9dd37c1d7b52d54
# via
- # -r requirements.in
# docker
# kubernetes
# requests
diff --git a/src/common/utils/jobs.py b/src/common/utils/jobs.py
index 9397f555d..8bec6df72 100644
--- a/src/common/utils/jobs.py
+++ b/src/common/utils/jobs.py
@@ -6,7 +6,7 @@ from hashlib import sha512
from inspect import getsourcefile
from io import BufferedReader
from json import dumps, loads
-from os.path import basename, normpath
+from os.path import basename
from pathlib import Path
from sys import _getframe
from threading import Lock
@@ -28,17 +28,19 @@ def is_cached_file(
expire: Union[Literal["hour"], Literal["day"], Literal["week"], Literal["month"]],
db=None,
) -> bool:
+ if not isinstance(file, Path):
+ file = Path(file)
+
is_cached = False
cached_file = None
try:
- file = normpath(file)
file_path = Path(f"{file}.md")
if not file_path.is_file():
if not db:
return False
cached_file = db.get_job_cache_file(
basename(getsourcefile(_getframe(1))).replace(".py", ""),
- basename(file),
+ file.name,
with_info=True,
)
@@ -65,16 +67,13 @@ def is_cached_file(
is_cached = False
if is_cached and cached_file:
- Path(file).write_bytes(cached_file.data)
+ file.write_bytes(cached_file.data)
return is_cached and cached_file
def get_file_in_db(file: Union[str, Path], db, *, job_name: Optional[str] = None) -> Optional[bytes]:
- cached_file = db.get_job_cache_file(
- job_name or basename(getsourcefile(_getframe(1))).replace(".py", ""),
- normpath(file),
- )
+ cached_file = db.get_job_cache_file(job_name or basename(getsourcefile(_getframe(1))).replace(".py", ""), file)
if not cached_file:
return None
return cached_file.data
@@ -107,10 +106,10 @@ def set_file_in_db(
return ret, err
-def del_file_in_db(name: str, db) -> Tuple[bool, str]:
+def del_file_in_db(name: str, db, *, service_id: Optional[str] = None) -> Tuple[bool, str]:
ret, err = True, "success"
try:
- db.delete_job_cache(name, job_name=basename(getsourcefile(_getframe(1))).replace(".py", ""))
+ db.delete_job_cache(name, job_name=basename(getsourcefile(_getframe(1))).replace(".py", ""), service_id=service_id)
except:
return False, f"exception :\n{format_exc()}"
return ret, err
@@ -118,7 +117,10 @@ def del_file_in_db(name: str, db) -> Tuple[bool, str]:
def file_hash(file: Union[str, Path]) -> str:
_sha512 = sha512()
- with open(normpath(file), "rb") as f:
+ if not isinstance(file, Path):
+ file = Path(file)
+
+ with file.open("rb") as f:
while True:
data = f.read(1024)
if not data:
@@ -139,18 +141,24 @@ def bytes_hash(bio: BufferedReader) -> str:
def cache_hash(cache: Union[str, Path], db=None) -> Optional[str]:
+ checksum = None
with suppress(BaseException):
- return loads(Path(normpath(f"{cache}.md")).read_text(encoding="utf-8")).get("checksum", None)
- if db:
+ checksum = loads(Path(f"{cache}.md").read_text(encoding="utf-8")).get("checksum", None)
+
+ if not checksum and db:
+ if not isinstance(cache, Path):
+ cache = Path(cache)
+
cached_file = db.get_job_cache_file(
basename(getsourcefile(_getframe(1))).replace(".py", ""),
- basename(normpath(cache)),
+ cache.name,
with_info=True,
with_data=False,
)
+ checksum = cached_file.checksum if cached_file else None
- if cached_file:
- return cached_file.checksum
+ if checksum:
+ return checksum
return None
@@ -166,9 +174,9 @@ def cache_file(
ret, err = True, "success"
try:
if not isinstance(file, Path):
- file = Path(normpath(file))
+ file = Path(file)
if not isinstance(cache, Path):
- cache = Path(normpath(cache))
+ cache = Path(cache)
content = file.read_bytes()
cache.write_bytes(content)
@@ -181,7 +189,7 @@ def cache_file(
if db:
return set_file_in_db(
- basename(str(cache)),
+ cache.name,
content,
db,
job_name=basename(getsourcefile(_getframe(1))).replace(".py", ""),
diff --git a/src/common/utils/logger.py b/src/common/utils/logger.py
index f9c4f99a7..541c6d7a7 100644
--- a/src/common/utils/logger.py
+++ b/src/common/utils/logger.py
@@ -30,12 +30,14 @@ basicConfig(
level=default_level,
)
-getLogger("sqlalchemy.orm.mapper.Mapper").setLevel(default_level if default_level != INFO else WARNING)
-getLogger("sqlalchemy.orm.relationships.RelationshipProperty").setLevel(default_level if default_level != INFO else WARNING)
-getLogger("sqlalchemy.orm.strategies.LazyLoader").setLevel(default_level if default_level != INFO else WARNING)
-getLogger("sqlalchemy.pool.impl.QueuePool").setLevel(default_level if default_level != INFO else WARNING)
-getLogger("sqlalchemy.pool.impl.SingletonThreadPool").setLevel(default_level if default_level != INFO else WARNING)
-getLogger("sqlalchemy.engine.Engine").setLevel(default_level if default_level != INFO else WARNING)
+database_default_level = _nameToLevel.get(getenv("DATABASE_LOG_LEVEL", "WARNING").upper(), WARNING)
+
+getLogger("sqlalchemy.orm.mapper.Mapper").setLevel(database_default_level)
+getLogger("sqlalchemy.orm.relationships.RelationshipProperty").setLevel(database_default_level)
+getLogger("sqlalchemy.orm.strategies.LazyLoader").setLevel(database_default_level)
+getLogger("sqlalchemy.pool.impl.QueuePool").setLevel(database_default_level)
+getLogger("sqlalchemy.pool.impl.SingletonThreadPool").setLevel(database_default_level)
+getLogger("sqlalchemy.engine.Engine").setLevel(database_default_level)
# Edit the default levels of the logging module
addLevelName(CRITICAL, "🚨")
diff --git a/src/deps/deps.json b/src/deps/deps.json
index 2cb51716c..f9c96c334 100644
--- a/src/deps/deps.json
+++ b/src/deps/deps.json
@@ -231,9 +231,9 @@
},
{
"id": "zlib",
- "name": "zlib v1.3",
+ "name": "zlib v1.3.1",
"url": "https://github.com/madler/zlib.git",
- "commit": "09155eaa2f9270dc4ed1fa13e2b4b2613e6e4851"
+ "commit": "51b7f2abdade71cd9bb0e7a373ef2610ec6f9daf"
},
{
"id": "lua-resty-redis-connector",
diff --git a/src/deps/src/zlib/.gitignore b/src/deps/src/zlib/.gitignore
index b1c7422fe..bd44d84af 100644
--- a/src/deps/src/zlib/.gitignore
+++ b/src/deps/src/zlib/.gitignore
@@ -16,7 +16,7 @@
/example
/example64
/examplesh
-/libz.so*
+**/libz.so*
/minigzip
/minigzip64
/minigzipsh
@@ -24,3 +24,13 @@
/configure.log
.DS_Store
+.vs
+*.user
+*.nupkg
+contrib/vstudio/vc143/x86
+contrib/vstudio/vc143/x64
+contrib/vstudio/vc143/arm
+contrib/vstudio/vc143/arm64
+contrib/nuget/bin
+contrib/nuget/obj
+*.included
diff --git a/src/deps/src/zlib/CMakeLists.txt b/src/deps/src/zlib/CMakeLists.txt
index 7f1b69f4a..15ceebe78 100644
--- a/src/deps/src/zlib/CMakeLists.txt
+++ b/src/deps/src/zlib/CMakeLists.txt
@@ -3,7 +3,9 @@ set(CMAKE_ALLOW_LOOSE_LOOP_CONSTRUCTS ON)
project(zlib C)
-set(VERSION "1.3")
+set(VERSION "1.3.1")
+
+option(ZLIB_BUILD_EXAMPLES "Enable Zlib Examples" ON)
set(INSTALL_BIN_DIR "${CMAKE_INSTALL_PREFIX}/bin" CACHE PATH "Installation directory for executables")
set(INSTALL_LIB_DIR "${CMAKE_INSTALL_PREFIX}/lib" CACHE PATH "Installation directory for libraries")
@@ -148,7 +150,9 @@ if(MINGW)
endif(MINGW)
add_library(zlib SHARED ${ZLIB_SRCS} ${ZLIB_DLL_SRCS} ${ZLIB_PUBLIC_HDRS} ${ZLIB_PRIVATE_HDRS})
+target_include_directories(zlib PUBLIC ${CMAKE_CURRENT_BINARY_DIR} ${CMAKE_CURRENT_SOURCE_DIR})
add_library(zlibstatic STATIC ${ZLIB_SRCS} ${ZLIB_PUBLIC_HDRS} ${ZLIB_PRIVATE_HDRS})
+target_include_directories(zlibstatic PUBLIC ${CMAKE_CURRENT_BINARY_DIR} ${CMAKE_CURRENT_SOURCE_DIR})
set_target_properties(zlib PROPERTIES DEFINE_SYMBOL ZLIB_DLL)
set_target_properties(zlib PROPERTIES SOVERSION 1)
@@ -166,7 +170,7 @@ endif()
if(UNIX)
# On unix-like platforms the library is almost always called libz
set_target_properties(zlib zlibstatic PROPERTIES OUTPUT_NAME z)
- if(NOT APPLE)
+ if(NOT APPLE AND NOT(CMAKE_SYSTEM_NAME STREQUAL AIX))
set_target_properties(zlib PROPERTIES LINK_FLAGS "-Wl,--version-script,\"${CMAKE_CURRENT_SOURCE_DIR}/zlib.map\"")
endif()
elseif(BUILD_SHARED_LIBS AND WIN32)
@@ -193,21 +197,22 @@ endif()
#============================================================================
# Example binaries
#============================================================================
+if(ZLIB_BUILD_EXAMPLES)
+ add_executable(example test/example.c)
+ target_link_libraries(example zlib)
+ add_test(example example)
-add_executable(example test/example.c)
-target_link_libraries(example zlib)
-add_test(example example)
+ add_executable(minigzip test/minigzip.c)
+ target_link_libraries(minigzip zlib)
-add_executable(minigzip test/minigzip.c)
-target_link_libraries(minigzip zlib)
+ if(HAVE_OFF64_T)
+ add_executable(example64 test/example.c)
+ target_link_libraries(example64 zlib)
+ set_target_properties(example64 PROPERTIES COMPILE_FLAGS "-D_FILE_OFFSET_BITS=64")
+ add_test(example64 example64)
-if(HAVE_OFF64_T)
- add_executable(example64 test/example.c)
- target_link_libraries(example64 zlib)
- set_target_properties(example64 PROPERTIES COMPILE_FLAGS "-D_FILE_OFFSET_BITS=64")
- add_test(example64 example64)
-
- add_executable(minigzip64 test/minigzip.c)
- target_link_libraries(minigzip64 zlib)
- set_target_properties(minigzip64 PROPERTIES COMPILE_FLAGS "-D_FILE_OFFSET_BITS=64")
+ add_executable(minigzip64 test/minigzip.c)
+ target_link_libraries(minigzip64 zlib)
+ set_target_properties(minigzip64 PROPERTIES COMPILE_FLAGS "-D_FILE_OFFSET_BITS=64")
+ endif()
endif()
diff --git a/src/deps/src/zlib/ChangeLog b/src/deps/src/zlib/ChangeLog
index 8707988ac..b801a1031 100644
--- a/src/deps/src/zlib/ChangeLog
+++ b/src/deps/src/zlib/ChangeLog
@@ -1,6 +1,16 @@
ChangeLog file for zlib
+Changes in 1.3.1 (22 Jan 2024)
+- Reject overflows of zip header fields in minizip
+- Fix bug in inflateSync() for data held in bit buffer
+- Add LIT_MEM define to use more memory for a small deflate speedup
+- Fix decision on the emission of Zip64 end records in minizip
+- Add bounds checking to ERR_MSG() macro, used by zError()
+- Neutralize zip file traversal attacks in miniunz
+- Fix a bug in ZLIB_DEBUG compiles in check_match()
+- Various portability and appearance improvements
+
Changes in 1.3 (18 Aug 2023)
- Remove K&R function definitions and zlib2ansi
- Fix bug in deflateBound() for level 0 and memLevel 9
diff --git a/src/deps/src/zlib/FAQ b/src/deps/src/zlib/FAQ
index 55f1cdc22..92f5d3e29 100644
--- a/src/deps/src/zlib/FAQ
+++ b/src/deps/src/zlib/FAQ
@@ -14,8 +14,7 @@ The latest zlib FAQ is at http://zlib.net/zlib_faq.html
2. Where can I get a Windows DLL version?
The zlib sources can be compiled without change to produce a DLL. See the
- file win32/DLL_FAQ.txt in the zlib distribution. Pointers to the
- precompiled DLL are found in the zlib web site at http://zlib.net/ .
+ file win32/DLL_FAQ.txt in the zlib distribution.
3. Where can I get a Visual Basic interface to zlib?
diff --git a/src/deps/src/zlib/Makefile.in b/src/deps/src/zlib/Makefile.in
index 34d3cd722..cb8b00a9b 100644
--- a/src/deps/src/zlib/Makefile.in
+++ b/src/deps/src/zlib/Makefile.in
@@ -1,5 +1,5 @@
# Makefile for zlib
-# Copyright (C) 1995-2017 Jean-loup Gailly, Mark Adler
+# Copyright (C) 1995-2024 Jean-loup Gailly, Mark Adler
# For conditions of distribution and use, see copyright notice in zlib.h
# To compile and test, type:
@@ -22,13 +22,13 @@ CFLAGS=-O
SFLAGS=-O
LDFLAGS=
-TEST_LDFLAGS=$(LDFLAGS) -L. libz.a
+TEST_LIBS=-L. libz.a
LDSHARED=$(CC)
CPP=$(CC) -E
STATICLIB=libz.a
SHAREDLIB=libz.so
-SHAREDLIBV=libz.so.1.3
+SHAREDLIBV=libz.so.1.3.1
SHAREDLIBM=libz.so.1
LIBS=$(STATICLIB) $(SHAREDLIBV)
@@ -282,10 +282,10 @@ placebo $(SHAREDLIBV): $(PIC_OBJS) libz.a
-@rmdir objs
example$(EXE): example.o $(STATICLIB)
- $(CC) $(CFLAGS) -o $@ example.o $(TEST_LDFLAGS)
+ $(CC) $(CFLAGS) $(LDFLAGS) -o $@ example.o $(TEST_LIBS)
minigzip$(EXE): minigzip.o $(STATICLIB)
- $(CC) $(CFLAGS) -o $@ minigzip.o $(TEST_LDFLAGS)
+ $(CC) $(CFLAGS) $(LDFLAGS) -o $@ minigzip.o $(TEST_LIBS)
examplesh$(EXE): example.o $(SHAREDLIBV)
$(CC) $(CFLAGS) -o $@ example.o $(LDFLAGS) -L. $(SHAREDLIBV)
@@ -294,10 +294,10 @@ minigzipsh$(EXE): minigzip.o $(SHAREDLIBV)
$(CC) $(CFLAGS) -o $@ minigzip.o $(LDFLAGS) -L. $(SHAREDLIBV)
example64$(EXE): example64.o $(STATICLIB)
- $(CC) $(CFLAGS) -o $@ example64.o $(TEST_LDFLAGS)
+ $(CC) $(CFLAGS) $(LDFLAGS) -o $@ example64.o $(TEST_LIBS)
minigzip64$(EXE): minigzip64.o $(STATICLIB)
- $(CC) $(CFLAGS) -o $@ minigzip64.o $(TEST_LDFLAGS)
+ $(CC) $(CFLAGS) $(LDFLAGS) -o $@ minigzip64.o $(TEST_LIBS)
install-libs: $(LIBS)
-@if [ ! -d $(DESTDIR)$(exec_prefix) ]; then mkdir -p $(DESTDIR)$(exec_prefix); fi
@@ -360,7 +360,7 @@ zconf: $(SRCDIR)zconf.h.in
cp -p $(SRCDIR)zconf.h.in zconf.h
minizip-test: static
- cd contrib/minizip && { CFLAGS="$(CFLAGS)" $(MAKE) test ; cd ../.. ; }
+ cd contrib/minizip && { CC="$(CC)" CFLAGS="$(CFLAGS)" $(MAKE) test ; cd ../.. ; }
minizip-clean:
cd contrib/minizip && { $(MAKE) clean ; cd ../.. ; }
diff --git a/src/deps/src/zlib/README b/src/deps/src/zlib/README
index e02fc5aa2..c5f917540 100644
--- a/src/deps/src/zlib/README
+++ b/src/deps/src/zlib/README
@@ -1,6 +1,6 @@
ZLIB DATA COMPRESSION LIBRARY
-zlib 1.3 is a general purpose data compression library. All the code is
+zlib 1.3.1 is a general purpose data compression library. All the code is
thread safe. The data format used by the zlib library is described by RFCs
(Request for Comments) 1950 to 1952 in the files
http://tools.ietf.org/html/rfc1950 (zlib format), rfc1951 (deflate format) and
@@ -31,7 +31,7 @@ Mark Nelson wrote an article about zlib for the Jan. 1997
issue of Dr. Dobb's Journal; a copy of the article is available at
https://marknelson.us/posts/1997/01/01/zlib-engine.html .
-The changes made in version 1.3 are documented in the file ChangeLog.
+The changes made in version 1.3.1 are documented in the file ChangeLog.
Unsupported third party contributions are provided in directory contrib/ .
@@ -83,7 +83,7 @@ Acknowledgments:
Copyright notice:
- (C) 1995-2023 Jean-loup Gailly and Mark Adler
+ (C) 1995-2024 Jean-loup Gailly and Mark Adler
This software is provided 'as-is', without any express or implied
warranty. In no event will the authors be held liable for any damages
diff --git a/src/deps/src/zlib/configure b/src/deps/src/zlib/configure
index cc867c944..c55098afc 100755
--- a/src/deps/src/zlib/configure
+++ b/src/deps/src/zlib/configure
@@ -25,7 +25,7 @@ if test $SRCDIR = "."; then
ZINCOUT="-I."
SRCDIR=""
else
- ZINC='-include zconf.h'
+ ZINC='-I. -include zconf.h'
ZINCOUT='-I. -I$(SRCDIR)'
SRCDIR="$SRCDIR/"
fi
@@ -44,7 +44,8 @@ STATICLIB=libz.a
# extract zlib version numbers from zlib.h
VER=`sed -n -e '/VERSION "/s/.*"\(.*\)".*/\1/p' < ${SRCDIR}zlib.h`
-VER1=`sed -n -e '/VERSION "/s/.*"\([0-9]*\)\\..*/\1/p' < ${SRCDIR}zlib.h`
+VER3=`echo ${VER}|sed -n -e 's/\([0-9]\{1,\}\(\\.[0-9]\{1,\}\)\{1,2\}\).*/\1/p'`
+VER1=`echo ${VER}|sed -n -e 's/\([0-9]\{1,\}\)\\..*/\1/p'`
# establish commands for library building
if "${CROSS_PREFIX}ar" --version >/dev/null 2>/dev/null || test $? -lt 126; then
@@ -263,7 +264,7 @@ if test "$gcc" -eq 1 && ($cc -c $test.c) >> configure.log 2>&1; then
SHAREDLIB=libz$shared_ext
SHAREDLIBV=libz.$VER$shared_ext
SHAREDLIBM=libz.$VER1$shared_ext
- LDSHARED=${LDSHARED-"$cc -dynamiclib -install_name $libdir/$SHAREDLIBM -compatibility_version $VER1 -current_version $VER"}
+ LDSHARED=${LDSHARED-"$cc -dynamiclib -install_name $libdir/$SHAREDLIBM -compatibility_version $VER1 -current_version $VER3"}
if "${CROSS_PREFIX}libtool" -V 2>&1 | grep Apple > /dev/null; then
AR="${CROSS_PREFIX}libtool"
elif libtool -V 2>&1 | grep Apple > /dev/null; then
@@ -441,7 +442,7 @@ EOF
if test $shared -eq 1; then
echo Checking for shared library support... | tee -a configure.log
# we must test in two steps (cc then ld), required at least on SunOS 4.x
- if try $CC -w -c $SFLAGS $test.c &&
+ if try $CC -c $SFLAGS $test.c &&
try $LDSHARED $SFLAGS -o $test$shared_ext $test.o; then
echo Building shared library $SHAREDLIBV with $CC. | tee -a configure.log
elif test -z "$old_cc" -a -z "$old_cflags"; then
diff --git a/src/deps/src/zlib/contrib/delphi/ZLib.pas b/src/deps/src/zlib/contrib/delphi/ZLib.pas
index 814ffa670..93fa4c9ed 100644
--- a/src/deps/src/zlib/contrib/delphi/ZLib.pas
+++ b/src/deps/src/zlib/contrib/delphi/ZLib.pas
@@ -152,7 +152,7 @@ procedure DecompressToUserBuf(const InBuf: Pointer; InBytes: Integer;
const OutBuf: Pointer; BufSize: Integer);
const
- zlib_version = '1.3.0';
+ zlib_version = '1.3.1';
type
EZlibError = class(Exception);
diff --git a/src/deps/src/zlib/contrib/dotzlib/DotZLib/ChecksumImpl.cs b/src/deps/src/zlib/contrib/dotzlib/DotZLib/ChecksumImpl.cs
index c1230bf03..de88dcf11 100644
--- a/src/deps/src/zlib/contrib/dotzlib/DotZLib/ChecksumImpl.cs
+++ b/src/deps/src/zlib/contrib/dotzlib/DotZLib/ChecksumImpl.cs
@@ -34,7 +34,7 @@ namespace DotZLib
}
///
- /// Initializes a new instance of the checksum generator basewith a specified value
+ /// Initializes a new instance of the checksum generator base with a specified value
///
/// The value to set the current checksum to
public ChecksumGeneratorBase(uint initialValue)
diff --git a/src/deps/src/zlib/contrib/dotzlib/DotZLib/UnitTests.cs b/src/deps/src/zlib/contrib/dotzlib/DotZLib/UnitTests.cs
index c5fce221a..d4f098023 100644
--- a/src/deps/src/zlib/contrib/dotzlib/DotZLib/UnitTests.cs
+++ b/src/deps/src/zlib/contrib/dotzlib/DotZLib/UnitTests.cs
@@ -156,7 +156,7 @@ namespace DotZLibTests
public void Info_Version()
{
Info info = new Info();
- Assert.AreEqual("1.3.0", Info.Version);
+ Assert.AreEqual("1.3.1", Info.Version);
Assert.AreEqual(32, info.SizeOfUInt);
Assert.AreEqual(32, info.SizeOfULong);
Assert.AreEqual(32, info.SizeOfPointer);
diff --git a/src/deps/src/zlib/contrib/infback9/inftree9.c b/src/deps/src/zlib/contrib/infback9/inftree9.c
index dc38f24de..ac707ed3f 100644
--- a/src/deps/src/zlib/contrib/infback9/inftree9.c
+++ b/src/deps/src/zlib/contrib/infback9/inftree9.c
@@ -1,5 +1,5 @@
/* inftree9.c -- generate Huffman trees for efficient decoding
- * Copyright (C) 1995-2023 Mark Adler
+ * Copyright (C) 1995-2024 Mark Adler
* For conditions of distribution and use, see copyright notice in zlib.h
*/
@@ -9,7 +9,7 @@
#define MAXBITS 15
const char inflate9_copyright[] =
- " inflate9 1.3 Copyright 1995-2023 Mark Adler ";
+ " inflate9 1.3.1 Copyright 1995-2024 Mark Adler ";
/*
If you use the zlib library in a product, an acknowledgment is welcome
in the documentation of your product. If for some reason you cannot
@@ -59,7 +59,7 @@ int inflate_table9(codetype type, unsigned short FAR *lens, unsigned codes,
static const unsigned short lext[31] = { /* Length codes 257..285 extra */
128, 128, 128, 128, 128, 128, 128, 128, 129, 129, 129, 129,
130, 130, 130, 130, 131, 131, 131, 131, 132, 132, 132, 132,
- 133, 133, 133, 133, 144, 198, 203};
+ 133, 133, 133, 133, 144, 203, 77};
static const unsigned short dbase[32] = { /* Distance codes 0..31 base */
1, 2, 3, 4, 5, 7, 9, 13, 17, 25, 33, 49,
65, 97, 129, 193, 257, 385, 513, 769, 1025, 1537, 2049, 3073,
diff --git a/src/deps/src/zlib/contrib/infback9/inftree9.h b/src/deps/src/zlib/contrib/infback9/inftree9.h
index 2c1252f57..ab2ea28b2 100644
--- a/src/deps/src/zlib/contrib/infback9/inftree9.h
+++ b/src/deps/src/zlib/contrib/infback9/inftree9.h
@@ -41,8 +41,8 @@ typedef struct {
examples/enough.c found in the zlib distribution. The arguments to that
program are the number of symbols, the initial root table size, and the
maximum bit length of a code. "enough 286 9 15" for literal/length codes
- returns returns 852, and "enough 32 6 15" for distance codes returns 594.
- The initial root table size (9 or 6) is found in the fifth argument of the
+ returns 852, and "enough 32 6 15" for distance codes returns 594. The
+ initial root table size (9 or 6) is found in the fifth argument of the
inflate_table() calls in infback9.c. If the root table size is changed,
then these maximum sizes would be need to be recalculated and updated. */
#define ENOUGH_LENS 852
diff --git a/src/deps/src/zlib/contrib/iostream3/zfstream.h b/src/deps/src/zlib/contrib/iostream3/zfstream.h
index 8574479ae..3dabc0f97 100644
--- a/src/deps/src/zlib/contrib/iostream3/zfstream.h
+++ b/src/deps/src/zlib/contrib/iostream3/zfstream.h
@@ -413,7 +413,7 @@ template
class gzomanip2
{
public:
- // Allows insertor to peek at internals
+ // Allows inserter to peek at internals
template
friend gzofstream&
operator<<(gzofstream&,
@@ -452,7 +452,7 @@ template
: func(f), val1(v1), val2(v2)
{ }
-// Insertor applies underlying manipulator function to stream
+// Inserter applies underlying manipulator function to stream
template
inline gzofstream&
operator<<(gzofstream& s, const gzomanip2& m)
diff --git a/src/deps/src/zlib/contrib/minizip/Makefile b/src/deps/src/zlib/contrib/minizip/Makefile
index aac76e07f..3d927ec14 100644
--- a/src/deps/src/zlib/contrib/minizip/Makefile
+++ b/src/deps/src/zlib/contrib/minizip/Makefile
@@ -1,4 +1,4 @@
-CC=cc
+CC?=cc
CFLAGS := $(CFLAGS) -O -I../..
UNZ_OBJS = miniunz.o unzip.o ioapi.o ../../libz.a
diff --git a/src/deps/src/zlib/contrib/minizip/configure.ac b/src/deps/src/zlib/contrib/minizip/configure.ac
index df80e5b7e..15ec91718 100644
--- a/src/deps/src/zlib/contrib/minizip/configure.ac
+++ b/src/deps/src/zlib/contrib/minizip/configure.ac
@@ -1,7 +1,7 @@
# -*- Autoconf -*-
# Process this file with autoconf to produce a configure script.
-AC_INIT([minizip], [1.3.0], [bugzilla.redhat.com])
+AC_INIT([minizip], [1.3.1], [bugzilla.redhat.com])
AC_CONFIG_SRCDIR([minizip.c])
AM_INIT_AUTOMAKE([foreign])
LT_INIT
diff --git a/src/deps/src/zlib/contrib/minizip/ioapi.h b/src/deps/src/zlib/contrib/minizip/ioapi.h
index c588a18d0..a2d2e6e60 100644
--- a/src/deps/src/zlib/contrib/minizip/ioapi.h
+++ b/src/deps/src/zlib/contrib/minizip/ioapi.h
@@ -144,7 +144,7 @@ typedef long (ZCALLBACK *tell_file_func) (voidpf opaque, voidpf stream)
typedef long (ZCALLBACK *seek_file_func) (voidpf opaque, voidpf stream, uLong offset, int origin);
-/* here is the "old" 32 bits structure structure */
+/* here is the "old" 32 bits structure */
typedef struct zlib_filefunc_def_s
{
open_file_func zopen_file;
diff --git a/src/deps/src/zlib/contrib/minizip/miniunz.c b/src/deps/src/zlib/contrib/minizip/miniunz.c
index a12aec8be..d627c4226 100644
--- a/src/deps/src/zlib/contrib/minizip/miniunz.c
+++ b/src/deps/src/zlib/contrib/minizip/miniunz.c
@@ -79,7 +79,7 @@
/* change_file_date : change the date/time of a file
filename : the filename of the file where date/time must be modified
- dosdate : the new date at the MSDos format (4 bytes)
+ dosdate : the new date at the MSDOS format (4 bytes)
tmu_date : the SAME new date at the tm_unz format */
static void change_file_date(const char *filename, uLong dosdate, tm_unz tmu_date) {
#ifdef _WIN32
@@ -186,7 +186,7 @@ static int makedir(const char *newdir) {
}
static void do_banner(void) {
- printf("MiniUnz 1.01b, demo of zLib + Unz package written by Gilles Vollant\n");
+ printf("MiniUnz 1.1, demo of zLib + Unz package written by Gilles Vollant\n");
printf("more info at http://www.winimage.com/zLibDll/unzip.html\n\n");
}
@@ -356,6 +356,20 @@ static int do_extract_currentfile(unzFile uf, const int* popt_extract_without_pa
else
write_filename = filename_withoutpath;
+ if (write_filename[0]!='\0')
+ {
+ const char* relative_check = write_filename;
+ while (relative_check[1]!='\0')
+ {
+ if (relative_check[0]=='.' && relative_check[1]=='.')
+ write_filename = relative_check;
+ relative_check++;
+ }
+ }
+
+ while (write_filename[0]=='/' || write_filename[0]=='.')
+ write_filename++;
+
err = unzOpenCurrentFilePassword(uf,password);
if (err!=UNZ_OK)
{
diff --git a/src/deps/src/zlib/contrib/minizip/unzip.c b/src/deps/src/zlib/contrib/minizip/unzip.c
index ed763f89f..ea05b7d62 100644
--- a/src/deps/src/zlib/contrib/minizip/unzip.c
+++ b/src/deps/src/zlib/contrib/minizip/unzip.c
@@ -117,7 +117,7 @@
const char unz_copyright[] =
" unzip 1.01 Copyright 1998-2004 Gilles Vollant - http://www.winimage.com/zLibDll";
-/* unz_file_info_interntal contain internal info about a file in zipfile*/
+/* unz_file_info64_internal contain internal info about a file in zipfile*/
typedef struct unz_file_info64_internal_s
{
ZPOS64_T offset_curfile;/* relative offset of local header 8 bytes */
@@ -450,7 +450,7 @@ local ZPOS64_T unz64local_SearchCentralDir64(const zlib_filefunc64_32_def* pzlib
if (unz64local_getLong(pzlib_filefunc_def,filestream,&uL)!=UNZ_OK)
return CENTRALDIRINVALID;
- /* number of the disk with the start of the zip64 end of central directory */
+ /* number of the disk with the start of the zip64 end of central directory */
if (unz64local_getLong(pzlib_filefunc_def,filestream,&uL)!=UNZ_OK)
return CENTRALDIRINVALID;
if (uL != 0)
@@ -497,9 +497,9 @@ local unzFile unzOpenInternal(const void *path,
ZPOS64_T central_pos;
uLong uL;
- uLong number_disk; /* number of the current dist, used for
+ uLong number_disk; /* number of the current disk, used for
spanning ZIP, unsupported, always 0*/
- uLong number_disk_with_CD; /* number the the disk with central dir, used
+ uLong number_disk_with_CD; /* number the disk with central dir, used
for spanning ZIP, unsupported, always 0*/
ZPOS64_T number_entry_CD; /* total number of entries in
the central dir
diff --git a/src/deps/src/zlib/contrib/minizip/unzip.h b/src/deps/src/zlib/contrib/minizip/unzip.h
index 14105840f..5cfc9c627 100644
--- a/src/deps/src/zlib/contrib/minizip/unzip.h
+++ b/src/deps/src/zlib/contrib/minizip/unzip.h
@@ -306,7 +306,7 @@ extern int ZEXPORT unzGetCurrentFileInfo(unzFile file,
Get Info about the current file
if pfile_info!=NULL, the *pfile_info structure will contain some info about
the current file
- if szFileName!=NULL, the filemane string will be copied in szFileName
+ if szFileName!=NULL, the filename string will be copied in szFileName
(fileNameBufferSize is the size of the buffer)
if extraField!=NULL, the extra field information will be copied in extraField
(extraFieldBufferSize is the size of the buffer).
diff --git a/src/deps/src/zlib/contrib/minizip/zip.c b/src/deps/src/zlib/contrib/minizip/zip.c
index 3d3d4cadd..60bdffac3 100644
--- a/src/deps/src/zlib/contrib/minizip/zip.c
+++ b/src/deps/src/zlib/contrib/minizip/zip.c
@@ -575,7 +575,7 @@ local ZPOS64_T zip64local_SearchCentralDir64(const zlib_filefunc64_32_def* pzlib
if (zip64local_getLong(pzlib_filefunc_def,filestream,&uL)!=ZIP_OK)
return 0;
- /* number of the disk with the start of the zip64 end of central directory */
+ /* number of the disk with the start of the zip64 end of central directory */
if (zip64local_getLong(pzlib_filefunc_def,filestream,&uL)!=ZIP_OK)
return 0;
if (uL != 0)
@@ -614,9 +614,9 @@ local int LoadCentralDirectoryRecord(zip64_internal* pziinit) {
ZPOS64_T central_pos;
uLong uL;
- uLong number_disk; /* number of the current dist, used for
+ uLong number_disk; /* number of the current disk, used for
spanning ZIP, unsupported, always 0*/
- uLong number_disk_with_CD; /* number the the disk with central dir, used
+ uLong number_disk_with_CD; /* number of the disk with central dir, used
for spanning ZIP, unsupported, always 0*/
ZPOS64_T number_entry;
ZPOS64_T number_entry_CD; /* total number of entries in
@@ -1043,6 +1043,17 @@ extern int ZEXPORT zipOpenNewFileInZip4_64(zipFile file, const char* filename, c
return ZIP_PARAMERROR;
#endif
+ // The filename and comment length must fit in 16 bits.
+ if ((filename!=NULL) && (strlen(filename)>0xffff))
+ return ZIP_PARAMERROR;
+ if ((comment!=NULL) && (strlen(comment)>0xffff))
+ return ZIP_PARAMERROR;
+ // The extra field length must fit in 16 bits. If the member also requires
+ // a Zip64 extra block, that will also need to fit within that 16-bit
+ // length, but that will be checked for later.
+ if ((size_extrafield_local>0xffff) || (size_extrafield_global>0xffff))
+ return ZIP_PARAMERROR;
+
zi = (zip64_internal*)file;
if (zi->in_opened_file_inzip == 1)
@@ -1597,7 +1608,7 @@ extern int ZEXPORT zipCloseFileInZipRaw64(zipFile file, ZPOS64_T uncompressed_si
if((uLong)(datasize + 4) > zi->ci.size_centralExtraFree)
{
- // we can not write more data to the buffer that we have room for.
+ // we cannot write more data to the buffer that we have room for.
return ZIP_BADZIPFILE;
}
@@ -1861,7 +1872,7 @@ extern int ZEXPORT zipClose(zipFile file, const char* global_comment) {
free_linkedlist(&(zi->central_dir));
pos = centraldir_pos_inzip - zi->add_position_when_writing_offset;
- if(pos >= 0xffffffff || zi->number_entry > 0xFFFF)
+ if(pos >= 0xffffffff || zi->number_entry >= 0xFFFF)
{
ZPOS64_T Zip64EOCDpos = ZTELL64(zi->z_filefunc,zi->filestream);
Write_Zip64EndOfCentralDirectoryRecord(zi, size_centraldir, centraldir_pos_inzip);
diff --git a/src/deps/src/zlib/contrib/minizip/zip.h b/src/deps/src/zlib/contrib/minizip/zip.h
index 5fc084132..3e230d340 100644
--- a/src/deps/src/zlib/contrib/minizip/zip.h
+++ b/src/deps/src/zlib/contrib/minizip/zip.h
@@ -177,9 +177,9 @@ extern int ZEXPORT zipOpenNewFileInZip64(zipFile file,
filename : the filename in zip (if NULL, '-' without quote will be used
*zipfi contain supplemental information
if extrafield_local!=NULL and size_extrafield_local>0, extrafield_local
- contains the extrafield data the the local header
+ contains the extrafield data for the local header
if extrafield_global!=NULL and size_extrafield_global>0, extrafield_global
- contains the extrafield data the the local header
+ contains the extrafield data for the global header
if comment != NULL, comment contain the comment string
method contain the compression method (0 for store, Z_DEFLATED for deflate)
level contain the level of compression (can be Z_DEFAULT_COMPRESSION)
diff --git a/src/deps/src/zlib/contrib/nuget/nuget.csproj b/src/deps/src/zlib/contrib/nuget/nuget.csproj
new file mode 100644
index 000000000..68627f034
--- /dev/null
+++ b/src/deps/src/zlib/contrib/nuget/nuget.csproj
@@ -0,0 +1,43 @@
+
+
+
+ net6.0
+ madler.zlib.redist
+ $(PackageId).win
+ $(PackageId).linux
+ $(PackageId).osx
+ (C) 1995-2024 Jean-loup Gailly and Mark Adler
+ 1.3.1
+ NuGet Package for consuming native builds of zlib into .NET without complexity.
+
+ NU5128
+ $(MSBuildProjectDirectory)
+ Jean-loup Gailly and Mark Adler
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/src/deps/src/zlib/contrib/nuget/nuget.sln b/src/deps/src/zlib/contrib/nuget/nuget.sln
new file mode 100644
index 000000000..46ee8deab
--- /dev/null
+++ b/src/deps/src/zlib/contrib/nuget/nuget.sln
@@ -0,0 +1,22 @@
+
+Microsoft Visual Studio Solution File, Format Version 12.00
+# Visual Studio Version 17
+VisualStudioVersion = 17.0.31903.59
+MinimumVisualStudioVersion = 10.0.40219.1
+Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "nuget", "nuget.csproj", "{B1BD3984-EF8F-4E9D-9A94-EB784E5EB1E8}"
+EndProject
+Global
+ GlobalSection(SolutionConfigurationPlatforms) = preSolution
+ Debug|Any CPU = Debug|Any CPU
+ Release|Any CPU = Release|Any CPU
+ EndGlobalSection
+ GlobalSection(SolutionProperties) = preSolution
+ HideSolutionNode = FALSE
+ EndGlobalSection
+ GlobalSection(ProjectConfigurationPlatforms) = postSolution
+ {B1BD3984-EF8F-4E9D-9A94-EB784E5EB1E8}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
+ {B1BD3984-EF8F-4E9D-9A94-EB784E5EB1E8}.Debug|Any CPU.Build.0 = Debug|Any CPU
+ {B1BD3984-EF8F-4E9D-9A94-EB784E5EB1E8}.Release|Any CPU.ActiveCfg = Release|Any CPU
+ {B1BD3984-EF8F-4E9D-9A94-EB784E5EB1E8}.Release|Any CPU.Build.0 = Release|Any CPU
+ EndGlobalSection
+EndGlobal
diff --git a/src/deps/src/zlib/contrib/pascal/zlibpas.pas b/src/deps/src/zlib/contrib/pascal/zlibpas.pas
index a2b24a593..0cf0e7b82 100644
--- a/src/deps/src/zlib/contrib/pascal/zlibpas.pas
+++ b/src/deps/src/zlib/contrib/pascal/zlibpas.pas
@@ -10,7 +10,7 @@ unit zlibpas;
interface
const
- ZLIB_VERSION = '1.3.0';
+ ZLIB_VERSION = '1.3.1';
ZLIB_VERNUM = $12a0;
type
diff --git a/src/deps/src/zlib/contrib/puff/puff.c b/src/deps/src/zlib/contrib/puff/puff.c
index 6737ff615..d759825ab 100644
--- a/src/deps/src/zlib/contrib/puff/puff.c
+++ b/src/deps/src/zlib/contrib/puff/puff.c
@@ -593,10 +593,10 @@ local int fixed(struct state *s)
* provided for each of the literal/length symbols, and for each of the
* distance symbols.
*
- * - If a symbol is not used in the block, this is represented by a zero as
- * as the code length. This does not mean a zero-length code, but rather
- * that no code should be created for this symbol. There is no way in the
- * deflate format to represent a zero-length code.
+ * - If a symbol is not used in the block, this is represented by a zero as the
+ * code length. This does not mean a zero-length code, but rather that no
+ * code should be created for this symbol. There is no way in the deflate
+ * format to represent a zero-length code.
*
* - The maximum number of bits in a code is 15, so the possible lengths for
* any code are 1..15.
diff --git a/src/deps/src/zlib/contrib/vstudio/readme.txt b/src/deps/src/zlib/contrib/vstudio/readme.txt
index 05ba487c9..061bbc0e2 100644
--- a/src/deps/src/zlib/contrib/vstudio/readme.txt
+++ b/src/deps/src/zlib/contrib/vstudio/readme.txt
@@ -1,75 +1,81 @@
-Building instructions for the DLL versions of Zlib 1.3.0
-========================================================
-
-This directory contains projects that build zlib and minizip using
-Microsoft Visual C++ 9.0/10.0.
-
-You don't need to build these projects yourself. You can download the
-binaries from:
- http://www.winimage.com/zLibDll
-
-More information can be found at this site.
-
-
-
-
-
-Build instructions for Visual Studio 2008 (32 bits or 64 bits)
---------------------------------------------------------------
-- Decompress current zlib, including all contrib/* files
-- Open contrib\vstudio\vc9\zlibvc.sln with Microsoft Visual C++ 2008
-- Or run: vcbuild /rebuild contrib\vstudio\vc9\zlibvc.sln "Release|Win32"
-
-Build instructions for Visual Studio 2010 (32 bits or 64 bits)
---------------------------------------------------------------
-- Decompress current zlib, including all contrib/* files
-- Open contrib\vstudio\vc10\zlibvc.sln with Microsoft Visual C++ 2010
-
-Build instructions for Visual Studio 2012 (32 bits or 64 bits)
---------------------------------------------------------------
-- Decompress current zlib, including all contrib/* files
-- Open contrib\vstudio\vc11\zlibvc.sln with Microsoft Visual C++ 2012
-
-Build instructions for Visual Studio 2013 (32 bits or 64 bits)
---------------------------------------------------------------
-- Decompress current zlib, including all contrib/* files
-- Open contrib\vstudio\vc12\zlibvc.sln with Microsoft Visual C++ 2013
-
-Build instructions for Visual Studio 2015 (32 bits or 64 bits)
---------------------------------------------------------------
-- Decompress current zlib, including all contrib/* files
-- Open contrib\vstudio\vc14\zlibvc.sln with Microsoft Visual C++ 2015
-
-
-Important
----------
-- To use zlibwapi.dll in your application, you must define the
- macro ZLIB_WINAPI when compiling your application's source files.
-
-
-Additional notes
-----------------
-- This DLL, named zlibwapi.dll, is compatible to the old zlib.dll built
- by Gilles Vollant from the zlib 1.1.x sources, and distributed at
- http://www.winimage.com/zLibDll
- It uses the WINAPI calling convention for the exported functions, and
- includes the minizip functionality. If your application needs that
- particular build of zlib.dll, you can rename zlibwapi.dll to zlib.dll.
-
-- The new DLL was renamed because there exist several incompatible
- versions of zlib.dll on the Internet.
-
-- There is also an official DLL build of zlib, named zlib1.dll. This one
- is exporting the functions using the CDECL convention. See the file
- win32\DLL_FAQ.txt found in this zlib distribution.
-
-- There used to be a ZLIB_DLL macro in zlib 1.1.x, but now this symbol
- has a slightly different effect. To avoid compatibility problems, do
- not define it here.
-
-
-Gilles Vollant
-info@winimage.com
-
-Visual Studio 2013 and 2015 Projects from Sean Hunt
-seandhunt_7@yahoo.com
+Building instructions for the DLL versions of Zlib 1.3.1
+========================================================
+
+This directory contains projects that build zlib and minizip using
+Microsoft Visual C++ 9.0/10.0.
+
+You don't need to build these projects yourself. You can download the
+binaries from:
+ http://www.winimage.com/zLibDll
+
+More information can be found at this site.
+
+
+
+
+
+Build instructions for Visual Studio 2008 (32 bits or 64 bits)
+--------------------------------------------------------------
+- Decompress current zlib, including all contrib/* files
+- Open contrib\vstudio\vc9\zlibvc.sln with Microsoft Visual C++ 2008
+- Or run: vcbuild /rebuild contrib\vstudio\vc9\zlibvc.sln "Release|Win32"
+
+Build instructions for Visual Studio 2010 (32 bits or 64 bits)
+--------------------------------------------------------------
+- Decompress current zlib, including all contrib/* files
+- Open contrib\vstudio\vc10\zlibvc.sln with Microsoft Visual C++ 2010
+
+Build instructions for Visual Studio 2012 (32 bits or 64 bits)
+--------------------------------------------------------------
+- Decompress current zlib, including all contrib/* files
+- Open contrib\vstudio\vc11\zlibvc.sln with Microsoft Visual C++ 2012
+
+Build instructions for Visual Studio 2013 (32 bits or 64 bits)
+--------------------------------------------------------------
+- Decompress current zlib, including all contrib/* files
+- Open contrib\vstudio\vc12\zlibvc.sln with Microsoft Visual C++ 2013
+
+Build instructions for Visual Studio 2015 (32 bits or 64 bits)
+--------------------------------------------------------------
+- Decompress current zlib, including all contrib/* files
+- Open contrib\vstudio\vc14\zlibvc.sln with Microsoft Visual C++ 2015
+
+Build instructions for Visual Studio 2022 (64 bits)
+--------------------------------------------------------------
+- Decompress current zlib, including all contrib/* files
+- Open contrib\vstudio\vc143\zlibvc.sln with Microsoft Visual C++ 2022
+
+
+
+Important
+---------
+- To use zlibwapi.dll in your application, you must define the
+ macro ZLIB_WINAPI when compiling your application's source files.
+
+
+Additional notes
+----------------
+- This DLL, named zlibwapi.dll, is compatible to the old zlib.dll built
+ by Gilles Vollant from the zlib 1.1.x sources, and distributed at
+ http://www.winimage.com/zLibDll
+ It uses the WINAPI calling convention for the exported functions, and
+ includes the minizip functionality. If your application needs that
+ particular build of zlib.dll, you can rename zlibwapi.dll to zlib.dll.
+
+- The new DLL was renamed because there exist several incompatible
+ versions of zlib.dll on the Internet.
+
+- There is also an official DLL build of zlib, named zlib1.dll. This one
+ is exporting the functions using the CDECL convention. See the file
+ win32\DLL_FAQ.txt found in this zlib distribution.
+
+- There used to be a ZLIB_DLL macro in zlib 1.1.x, but now this symbol
+ has a slightly different effect. To avoid compatibility problems, do
+ not define it here.
+
+
+Gilles Vollant
+info@winimage.com
+
+Visual Studio 2013, 2015, and 2022 Projects from Sean Hunt
+seandhunt_7@yahoo.com
diff --git a/src/deps/src/zlib/contrib/vstudio/vc10/zlib.rc b/src/deps/src/zlib/contrib/vstudio/vc10/zlib.rc
index 29af8e11a..856bd11f0 100644
--- a/src/deps/src/zlib/contrib/vstudio/vc10/zlib.rc
+++ b/src/deps/src/zlib/contrib/vstudio/vc10/zlib.rc
@@ -2,8 +2,8 @@
#define IDR_VERSION1 1
IDR_VERSION1 VERSIONINFO MOVEABLE IMPURE LOADONCALL DISCARDABLE
- FILEVERSION 1, 3, 0, 0
- PRODUCTVERSION 1, 3, 0, 0
+ FILEVERSION 1, 3, 1, 0
+ PRODUCTVERSION 1, 3, 1, 0
FILEFLAGSMASK VS_FFI_FILEFLAGSMASK
FILEFLAGS 0
FILEOS VOS_DOS_WINDOWS32
@@ -17,12 +17,12 @@ BEGIN
BEGIN
VALUE "FileDescription", "zlib data compression and ZIP file I/O library\0"
- VALUE "FileVersion", "1.3.0\0"
+ VALUE "FileVersion", "1.3.1\0"
VALUE "InternalName", "zlib\0"
VALUE "OriginalFilename", "zlibwapi.dll\0"
VALUE "ProductName", "ZLib.DLL\0"
VALUE "Comments","DLL support by Alessandro Iacopetti & Gilles Vollant\0"
- VALUE "LegalCopyright", "(C) 1995-2023 Jean-loup Gailly & Mark Adler\0"
+ VALUE "LegalCopyright", "(C) 1995-2024 Jean-loup Gailly & Mark Adler\0"
END
END
BLOCK "VarFileInfo"
diff --git a/src/deps/src/zlib/contrib/vstudio/vc10/zlibvc.def b/src/deps/src/zlib/contrib/vstudio/vc10/zlibvc.def
index f28aa6c73..3234a02d9 100644
--- a/src/deps/src/zlib/contrib/vstudio/vc10/zlibvc.def
+++ b/src/deps/src/zlib/contrib/vstudio/vc10/zlibvc.def
@@ -1,7 +1,7 @@
LIBRARY
; zlib data compression and ZIP file I/O library
-VERSION 1.3
+VERSION 1.3.1
EXPORTS
adler32 @1
diff --git a/src/deps/src/zlib/contrib/vstudio/vc11/zlib.rc b/src/deps/src/zlib/contrib/vstudio/vc11/zlib.rc
index 29af8e11a..856bd11f0 100644
--- a/src/deps/src/zlib/contrib/vstudio/vc11/zlib.rc
+++ b/src/deps/src/zlib/contrib/vstudio/vc11/zlib.rc
@@ -2,8 +2,8 @@
#define IDR_VERSION1 1
IDR_VERSION1 VERSIONINFO MOVEABLE IMPURE LOADONCALL DISCARDABLE
- FILEVERSION 1, 3, 0, 0
- PRODUCTVERSION 1, 3, 0, 0
+ FILEVERSION 1, 3, 1, 0
+ PRODUCTVERSION 1, 3, 1, 0
FILEFLAGSMASK VS_FFI_FILEFLAGSMASK
FILEFLAGS 0
FILEOS VOS_DOS_WINDOWS32
@@ -17,12 +17,12 @@ BEGIN
BEGIN
VALUE "FileDescription", "zlib data compression and ZIP file I/O library\0"
- VALUE "FileVersion", "1.3.0\0"
+ VALUE "FileVersion", "1.3.1\0"
VALUE "InternalName", "zlib\0"
VALUE "OriginalFilename", "zlibwapi.dll\0"
VALUE "ProductName", "ZLib.DLL\0"
VALUE "Comments","DLL support by Alessandro Iacopetti & Gilles Vollant\0"
- VALUE "LegalCopyright", "(C) 1995-2023 Jean-loup Gailly & Mark Adler\0"
+ VALUE "LegalCopyright", "(C) 1995-2024 Jean-loup Gailly & Mark Adler\0"
END
END
BLOCK "VarFileInfo"
diff --git a/src/deps/src/zlib/contrib/vstudio/vc11/zlibvc.def b/src/deps/src/zlib/contrib/vstudio/vc11/zlibvc.def
index f28aa6c73..3234a02d9 100644
--- a/src/deps/src/zlib/contrib/vstudio/vc11/zlibvc.def
+++ b/src/deps/src/zlib/contrib/vstudio/vc11/zlibvc.def
@@ -1,7 +1,7 @@
LIBRARY
; zlib data compression and ZIP file I/O library
-VERSION 1.3
+VERSION 1.3.1
EXPORTS
adler32 @1
diff --git a/src/deps/src/zlib/contrib/vstudio/vc12/zlib.rc b/src/deps/src/zlib/contrib/vstudio/vc12/zlib.rc
index 57fb31a32..a55f341c7 100644
--- a/src/deps/src/zlib/contrib/vstudio/vc12/zlib.rc
+++ b/src/deps/src/zlib/contrib/vstudio/vc12/zlib.rc
@@ -2,8 +2,8 @@
#define IDR_VERSION1 1
IDR_VERSION1 VERSIONINFO MOVEABLE IMPURE LOADONCALL DISCARDABLE
- FILEVERSION 1, 3, 0, 0
- PRODUCTVERSION 1, 3, 0, 0
+ FILEVERSION 1, 3, 1, 0
+ PRODUCTVERSION 1, 3, 1, 0
FILEFLAGSMASK VS_FFI_FILEFLAGSMASK
FILEFLAGS 0
FILEOS VOS_DOS_WINDOWS32
@@ -17,12 +17,12 @@ BEGIN
BEGIN
VALUE "FileDescription", "zlib data compression and ZIP file I/O library\0"
- VALUE "FileVersion", "1.3.0\0"
+ VALUE "FileVersion", "1.3.1\0"
VALUE "InternalName", "zlib\0"
VALUE "OriginalFilename", "zlibwapi.dll\0"
VALUE "ProductName", "ZLib.DLL\0"
VALUE "Comments","DLL support by Alessandro Iacopetti & Gilles Vollant\0"
- VALUE "LegalCopyright", "(C) 1995-2023 Jean-loup Gailly & Mark Adler\0"
+ VALUE "LegalCopyright", "(C) 1995-2024 Jean-loup Gailly & Mark Adler\0"
END
END
BLOCK "VarFileInfo"
diff --git a/src/deps/src/zlib/contrib/vstudio/vc12/zlibvc.def b/src/deps/src/zlib/contrib/vstudio/vc12/zlibvc.def
index f28aa6c73..3234a02d9 100644
--- a/src/deps/src/zlib/contrib/vstudio/vc12/zlibvc.def
+++ b/src/deps/src/zlib/contrib/vstudio/vc12/zlibvc.def
@@ -1,7 +1,7 @@
LIBRARY
; zlib data compression and ZIP file I/O library
-VERSION 1.3
+VERSION 1.3.1
EXPORTS
adler32 @1
diff --git a/src/deps/src/zlib/contrib/vstudio/vc14/zlib.rc b/src/deps/src/zlib/contrib/vstudio/vc14/zlib.rc
index 57fb31a32..a55f341c7 100644
--- a/src/deps/src/zlib/contrib/vstudio/vc14/zlib.rc
+++ b/src/deps/src/zlib/contrib/vstudio/vc14/zlib.rc
@@ -2,8 +2,8 @@
#define IDR_VERSION1 1
IDR_VERSION1 VERSIONINFO MOVEABLE IMPURE LOADONCALL DISCARDABLE
- FILEVERSION 1, 3, 0, 0
- PRODUCTVERSION 1, 3, 0, 0
+ FILEVERSION 1, 3, 1, 0
+ PRODUCTVERSION 1, 3, 1, 0
FILEFLAGSMASK VS_FFI_FILEFLAGSMASK
FILEFLAGS 0
FILEOS VOS_DOS_WINDOWS32
@@ -17,12 +17,12 @@ BEGIN
BEGIN
VALUE "FileDescription", "zlib data compression and ZIP file I/O library\0"
- VALUE "FileVersion", "1.3.0\0"
+ VALUE "FileVersion", "1.3.1\0"
VALUE "InternalName", "zlib\0"
VALUE "OriginalFilename", "zlibwapi.dll\0"
VALUE "ProductName", "ZLib.DLL\0"
VALUE "Comments","DLL support by Alessandro Iacopetti & Gilles Vollant\0"
- VALUE "LegalCopyright", "(C) 1995-2023 Jean-loup Gailly & Mark Adler\0"
+ VALUE "LegalCopyright", "(C) 1995-2024 Jean-loup Gailly & Mark Adler\0"
END
END
BLOCK "VarFileInfo"
diff --git a/src/deps/src/zlib/contrib/vstudio/vc14/zlibvc.def b/src/deps/src/zlib/contrib/vstudio/vc14/zlibvc.def
index f28aa6c73..3234a02d9 100644
--- a/src/deps/src/zlib/contrib/vstudio/vc14/zlibvc.def
+++ b/src/deps/src/zlib/contrib/vstudio/vc14/zlibvc.def
@@ -1,7 +1,7 @@
LIBRARY
; zlib data compression and ZIP file I/O library
-VERSION 1.3
+VERSION 1.3.1
EXPORTS
adler32 @1
diff --git a/src/deps/src/zlib/contrib/vstudio/vc17/miniunz.vcxproj b/src/deps/src/zlib/contrib/vstudio/vc17/miniunz.vcxproj
new file mode 100644
index 000000000..68ef16588
--- /dev/null
+++ b/src/deps/src/zlib/contrib/vstudio/vc17/miniunz.vcxproj
@@ -0,0 +1,409 @@
+
+
+
+
+ Debug
+ ARM
+
+
+ Debug
+ ARM64
+
+
+ Debug
+ Win32
+
+
+ Debug
+ x64
+
+
+ Release
+ ARM
+
+
+ Release
+ ARM64
+
+
+ Release
+ Win32
+
+
+ Release
+ x64
+
+
+
+ {C52F9E7B-498A-42BE-8DB4-85A15694382A}
+ Win32Proj
+ 10.0
+
+
+
+ Application
+ MultiByte
+ v143
+
+
+ Application
+ Unicode
+ v143
+
+
+ Application
+ MultiByte
+ v143
+
+
+ Application
+ MultiByte
+ v143
+
+
+ Application
+ MultiByte
+ v143
+
+
+ Application
+ MultiByte
+ v143
+
+
+ Application
+ MultiByte
+ v143
+
+
+ Application
+ MultiByte
+ v143
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ <_ProjectFileVersion>10.0.30128.1
+ x86\MiniUnzip$(Configuration)\
+ x86\MiniUnzip$(Configuration)\Tmp\
+ true
+ false
+ x86\MiniUnzip$(Configuration)\
+ x86\MiniUnzip$(Configuration)\Tmp\
+ false
+ false
+ x64\MiniUnzip$(Configuration)\
+ x64\MiniUnzip$(Configuration)\Tmp\
+ true
+ true
+ true
+ false
+ false
+ false
+ x64\MiniUnzip$(Configuration)\
+ x64\MiniUnzip$(Configuration)\Tmp\
+ false
+ false
+ false
+ false
+ false
+ false
+ AllRules.ruleset
+
+
+ AllRules.ruleset
+ AllRules.ruleset
+ AllRules.ruleset
+
+
+
+
+
+
+ AllRules.ruleset
+
+
+ AllRules.ruleset
+ AllRules.ruleset
+ AllRules.ruleset
+
+
+
+
+
+
+
+
+ arm64\MiniUnzip$(Configuration)\
+ arm64\MiniUnzip$(Configuration)\Tmp\
+
+
+ arm64\MiniUnzip$(Configuration)\
+ arm64\MiniUnzip$(Configuration)\Tmp\
+
+
+ arm\MiniUnzip$(Configuration)\
+ arm\MiniUnzip$(Configuration)\Tmp\
+
+
+ arm\MiniUnzip$(Configuration)\
+ arm\MiniUnzip$(Configuration)\Tmp\
+
+
+
+ Disabled
+ ..\..\..;..\..\minizip;%(AdditionalIncludeDirectories)
+ WIN32;_CRT_NONSTDC_NO_DEPRECATE;_CRT_SECURE_NO_DEPRECATE;ZLIB_WINAPI;_DEBUG;_CONSOLE;%(PreprocessorDefinitions)
+ true
+ Default
+ MultiThreadedDebugDLL
+ false
+
+
+ $(IntDir)
+ Level3
+ ProgramDatabase
+
+
+ x86\ZlibDllDebug\zlibwapi.lib;%(AdditionalDependencies)
+ $(OutDir)miniunz.exe
+ true
+ $(OutDir)miniunz.pdb
+ Console
+ false
+
+
+ MachineX86
+
+
+
+
+ MaxSpeed
+ OnlyExplicitInline
+ true
+ ..\..\..;..\..\minizip;%(AdditionalIncludeDirectories)
+ WIN32;_CRT_NONSTDC_NO_DEPRECATE;_CRT_SECURE_NO_DEPRECATE;ZLIB_WINAPI;NDEBUG;_CONSOLE;%(PreprocessorDefinitions)
+ true
+ Default
+ MultiThreaded
+ false
+ true
+
+
+ $(IntDir)
+ Level3
+ ProgramDatabase
+
+
+ x86\ZlibDllRelease\zlibwapi.lib;%(AdditionalDependencies)
+ $(OutDir)miniunz.exe
+ true
+ Console
+ true
+ true
+ false
+
+
+ MachineX86
+
+
+
+
+ X64
+
+
+ Disabled
+ ..\..\..;..\..\minizip;%(AdditionalIncludeDirectories)
+ _CRT_NONSTDC_NO_DEPRECATE;_CRT_SECURE_NO_DEPRECATE;ZLIB_WINAPI;_DEBUG;_CONSOLE;WIN64;%(PreprocessorDefinitions)
+ true
+ Default
+ MultiThreadedDebugDLL
+ false
+
+
+ $(IntDir)
+ Level3
+ ProgramDatabase
+
+
+ x64\ZlibDllDebug\zlibwapi.lib;%(AdditionalDependencies)
+ $(OutDir)miniunz.exe
+ true
+ $(OutDir)miniunz.pdb
+ Console
+ MachineX64
+
+
+
+
+
+ Disabled
+ ..\..\..;..\..\minizip;%(AdditionalIncludeDirectories)
+ _CRT_NONSTDC_NO_DEPRECATE;_CRT_SECURE_NO_DEPRECATE;ZLIB_WINAPI;_DEBUG;_CONSOLE;WIN64;%(PreprocessorDefinitions)
+ true
+ Default
+ MultiThreadedDebugDLL
+ false
+
+
+ $(IntDir)
+ Level3
+ ProgramDatabase
+
+
+ x64\ZlibDllDebug\zlibwapi.lib;%(AdditionalDependencies)
+ $(OutDir)miniunz.exe
+ true
+ $(OutDir)miniunz.pdb
+ Console
+
+
+
+
+
+ Disabled
+ ..\..\..;..\..\minizip;%(AdditionalIncludeDirectories)
+ _CRT_NONSTDC_NO_DEPRECATE;_CRT_SECURE_NO_DEPRECATE;ZLIB_WINAPI;_DEBUG;_CONSOLE;WIN64;%(PreprocessorDefinitions)
+ true
+ Default
+ MultiThreadedDebugDLL
+ false
+
+
+ $(IntDir)
+ Level3
+ ProgramDatabase
+
+
+ x64\ZlibDllDebug\zlibwapi.lib;%(AdditionalDependencies)
+ $(OutDir)miniunz.exe
+ true
+ $(OutDir)miniunz.pdb
+ Console
+
+
+
+
+ X64
+
+
+ MaxSpeed
+ OnlyExplicitInline
+ true
+ ..\..\..;..\..\minizip;%(AdditionalIncludeDirectories)
+ _CRT_NONSTDC_NO_DEPRECATE;_CRT_SECURE_NO_DEPRECATE;ZLIB_WINAPI;NDEBUG;_CONSOLE;WIN64;%(PreprocessorDefinitions)
+ true
+ Default
+ MultiThreadedDLL
+ false
+ true
+
+
+ $(IntDir)
+ Level3
+ ProgramDatabase
+
+
+ x64\ZlibDllRelease\zlibwapi.lib;%(AdditionalDependencies)
+ $(OutDir)miniunz.exe
+ true
+ Console
+ true
+ true
+ MachineX64
+
+
+
+
+
+ MaxSpeed
+ OnlyExplicitInline
+ true
+ ..\..\..;..\..\minizip;%(AdditionalIncludeDirectories)
+ _CRT_NONSTDC_NO_DEPRECATE;_CRT_SECURE_NO_DEPRECATE;ZLIB_WINAPI;NDEBUG;_CONSOLE;WIN64;%(PreprocessorDefinitions)
+ true
+ Default
+ MultiThreadedDLL
+ false
+ true
+
+
+ $(IntDir)
+ Level3
+ ProgramDatabase
+
+
+ x64\ZlibDllRelease\zlibwapi.lib;%(AdditionalDependencies)
+ $(OutDir)miniunz.exe
+ true
+ Console
+ true
+ true
+
+
+
+
+
+ MaxSpeed
+ OnlyExplicitInline
+ true
+ ..\..\..;..\..\minizip;%(AdditionalIncludeDirectories)
+ _CRT_NONSTDC_NO_DEPRECATE;_CRT_SECURE_NO_DEPRECATE;ZLIB_WINAPI;NDEBUG;_CONSOLE;WIN64;%(PreprocessorDefinitions)
+ true
+ Default
+ MultiThreadedDLL
+ false
+ true
+
+
+ $(IntDir)
+ Level3
+ ProgramDatabase
+
+
+ x64\ZlibDllRelease\zlibwapi.lib;%(AdditionalDependencies)
+ $(OutDir)miniunz.exe
+ true
+ Console
+ true
+ true
+
+
+
+
+
+
+
+ {8fd826f8-3739-44e6-8cc8-997122e53b8d}
+
+
+
+
+
+
\ No newline at end of file
diff --git a/src/deps/src/zlib/contrib/vstudio/vc17/minizip.vcxproj b/src/deps/src/zlib/contrib/vstudio/vc17/minizip.vcxproj
new file mode 100644
index 000000000..dd3c52e70
--- /dev/null
+++ b/src/deps/src/zlib/contrib/vstudio/vc17/minizip.vcxproj
@@ -0,0 +1,405 @@
+
+
+
+
+ Debug
+ ARM
+
+
+ Debug
+ ARM64
+
+
+ Debug
+ Win32
+
+
+ Debug
+ x64
+
+
+ Release
+ ARM
+
+
+ Release
+ ARM64
+
+
+ Release
+ Win32
+
+
+ Release
+ x64
+
+
+
+ {48CDD9DC-E09F-4135-9C0C-4FE50C3C654B}
+ Win32Proj
+ 10.0
+
+
+
+ Application
+ MultiByte
+ v143
+
+
+ Application
+ Unicode
+ v143
+
+
+ Application
+ MultiByte
+ v143
+
+
+ Application
+ MultiByte
+ v143
+
+
+ Application
+ MultiByte
+ v143
+
+
+ Application
+ MultiByte
+ v143
+
+
+ Application
+ MultiByte
+ v143
+
+
+ Application
+ MultiByte
+ v143
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ <_ProjectFileVersion>10.0.30128.1
+ x86\MiniZip$(Configuration)\
+ x86\MiniZip$(Configuration)\Tmp\
+ true
+ false
+ x86\MiniZip$(Configuration)\
+ x86\MiniZip$(Configuration)\Tmp\
+ false
+ x64\$(Configuration)\
+ x64\$(Configuration)\
+ true
+ true
+ true
+ false
+ false
+ false
+ x64\$(Configuration)\
+ x64\$(Configuration)\
+ false
+ false
+ false
+ AllRules.ruleset
+
+
+ AllRules.ruleset
+ AllRules.ruleset
+ AllRules.ruleset
+
+
+
+
+
+
+ AllRules.ruleset
+
+
+ AllRules.ruleset
+ AllRules.ruleset
+ AllRules.ruleset
+
+
+
+
+
+
+
+
+ arm64\MiniZip$(Configuration)\
+ arm64\MiniZip$(Configuration)\Tmp\
+
+
+ arm64\MiniZip$(Configuration)\
+ arm64\MiniZip$(Configuration)\Tmp\
+
+
+ arm\MiniZip$(Configuration)\
+ arm\MiniZip$(Configuration)\Tmp\
+
+
+ arm\MiniZip$(Configuration)\
+ arm\MiniZip$(Configuration)\Tmp\
+
+
+
+ Disabled
+ ..\..\..;..\..\minizip;%(AdditionalIncludeDirectories)
+ WIN32;_CRT_NONSTDC_NO_DEPRECATE;_CRT_SECURE_NO_DEPRECATE;ZLIB_WINAPI;_DEBUG;_CONSOLE;%(PreprocessorDefinitions)
+ true
+ Default
+ MultiThreadedDebugDLL
+ false
+
+
+ $(IntDir)
+ Level3
+ ProgramDatabase
+
+
+ x86\ZlibDllDebug\zlibwapi.lib;%(AdditionalDependencies)
+ $(OutDir)minizip.exe
+ true
+ $(OutDir)minizip.pdb
+ Console
+ false
+
+
+ MachineX86
+
+
+
+
+ MaxSpeed
+ OnlyExplicitInline
+ true
+ ..\..\..;..\..\minizip;%(AdditionalIncludeDirectories)
+ WIN32;_CRT_NONSTDC_NO_DEPRECATE;_CRT_SECURE_NO_DEPRECATE;ZLIB_WINAPI;NDEBUG;_CONSOLE;%(PreprocessorDefinitions)
+ true
+ Default
+ MultiThreaded
+ false
+ true
+
+
+ $(IntDir)
+ Level3
+ ProgramDatabase
+
+
+ x86\ZlibDllRelease\zlibwapi.lib;%(AdditionalDependencies)
+ $(OutDir)minizip.exe
+ true
+ Console
+ true
+ true
+ false
+
+
+ MachineX86
+
+
+
+
+ X64
+
+
+ Disabled
+ ..\..\..;..\..\minizip;%(AdditionalIncludeDirectories)
+ _CRT_NONSTDC_NO_DEPRECATE;_CRT_SECURE_NO_DEPRECATE;ZLIB_WINAPI;_DEBUG;_CONSOLE;WIN64;%(PreprocessorDefinitions)
+ true
+ Default
+ MultiThreadedDebugDLL
+ false
+
+
+ $(IntDir)
+ Level3
+ ProgramDatabase
+
+
+ x64\ZlibDllDebug\zlibwapi.lib;%(AdditionalDependencies)
+ $(OutDir)minizip.exe
+ true
+ $(OutDir)minizip.pdb
+ Console
+ MachineX64
+
+
+
+
+
+ Disabled
+ ..\..\..;..\..\minizip;%(AdditionalIncludeDirectories)
+ _CRT_NONSTDC_NO_DEPRECATE;_CRT_SECURE_NO_DEPRECATE;ZLIB_WINAPI;_DEBUG;_CONSOLE;WIN64;%(PreprocessorDefinitions)
+ true
+ Default
+ MultiThreadedDebugDLL
+ false
+
+
+ $(IntDir)
+ Level3
+ ProgramDatabase
+
+
+ x64\ZlibDllDebug\zlibwapi.lib;%(AdditionalDependencies)
+ $(OutDir)minizip.exe
+ true
+ $(OutDir)minizip.pdb
+ Console
+
+
+
+
+
+ Disabled
+ ..\..\..;..\..\minizip;%(AdditionalIncludeDirectories)
+ _CRT_NONSTDC_NO_DEPRECATE;_CRT_SECURE_NO_DEPRECATE;ZLIB_WINAPI;_DEBUG;_CONSOLE;WIN64;%(PreprocessorDefinitions)
+ true
+ Default
+ MultiThreadedDebugDLL
+ false
+
+
+ $(IntDir)
+ Level3
+ ProgramDatabase
+
+
+ x64\ZlibDllDebug\zlibwapi.lib;%(AdditionalDependencies)
+ $(OutDir)minizip.exe
+ true
+ $(OutDir)minizip.pdb
+ Console
+
+
+
+
+ X64
+
+
+ MaxSpeed
+ OnlyExplicitInline
+ true
+ ..\..\..;..\..\minizip;%(AdditionalIncludeDirectories)
+ _CRT_NONSTDC_NO_DEPRECATE;_CRT_SECURE_NO_DEPRECATE;ZLIB_WINAPI;NDEBUG;_CONSOLE;WIN64;%(PreprocessorDefinitions)
+ true
+ Default
+ MultiThreadedDLL
+ false
+ true
+
+
+ $(IntDir)
+ Level3
+ ProgramDatabase
+
+
+ x64\ZlibDllRelease\zlibwapi.lib;%(AdditionalDependencies)
+ $(OutDir)minizip.exe
+ true
+ Console
+ true
+ true
+ MachineX64
+
+
+
+
+
+ MaxSpeed
+ OnlyExplicitInline
+ true
+ ..\..\..;..\..\minizip;%(AdditionalIncludeDirectories)
+ _CRT_NONSTDC_NO_DEPRECATE;_CRT_SECURE_NO_DEPRECATE;ZLIB_WINAPI;NDEBUG;_CONSOLE;WIN64;%(PreprocessorDefinitions)
+ true
+ Default
+ MultiThreadedDLL
+ false
+ true
+
+
+ $(IntDir)
+ Level3
+ ProgramDatabase
+
+
+ x64\ZlibDllRelease\zlibwapi.lib;%(AdditionalDependencies)
+ $(OutDir)minizip.exe
+ true
+ Console
+ true
+ true
+
+
+
+
+
+ MaxSpeed
+ OnlyExplicitInline
+ true
+ ..\..\..;..\..\minizip;%(AdditionalIncludeDirectories)
+ _CRT_NONSTDC_NO_DEPRECATE;_CRT_SECURE_NO_DEPRECATE;ZLIB_WINAPI;NDEBUG;_CONSOLE;WIN64;%(PreprocessorDefinitions)
+ true
+ Default
+ MultiThreadedDLL
+ false
+ true
+
+
+ $(IntDir)
+ Level3
+ ProgramDatabase
+
+
+ x64\ZlibDllRelease\zlibwapi.lib;%(AdditionalDependencies)
+ $(OutDir)minizip.exe
+ true
+ Console
+ true
+ true
+
+
+
+
+
+
+
+ {8fd826f8-3739-44e6-8cc8-997122e53b8d}
+
+
+
+
+
+
\ No newline at end of file
diff --git a/src/deps/src/zlib/contrib/vstudio/vc17/testzlib.vcxproj b/src/deps/src/zlib/contrib/vstudio/vc17/testzlib.vcxproj
new file mode 100644
index 000000000..4cc99b3ff
--- /dev/null
+++ b/src/deps/src/zlib/contrib/vstudio/vc17/testzlib.vcxproj
@@ -0,0 +1,473 @@
+
+
+
+
+ Debug
+ ARM
+
+
+ Debug
+ ARM64
+
+
+ Debug
+ Win32
+
+
+ Debug
+ x64
+
+
+ ReleaseWithoutAsm
+ ARM
+
+
+ ReleaseWithoutAsm
+ ARM64
+
+
+ ReleaseWithoutAsm
+ Win32
+
+
+ ReleaseWithoutAsm
+ x64
+
+
+ Release
+ ARM
+
+
+ Release
+ ARM64
+
+
+ Release
+ Win32
+
+
+ Release
+ x64
+
+
+
+ {AA6666AA-E09F-4135-9C0C-4FE50C3C654B}
+ testzlib
+ Win32Proj
+ 10.0
+
+
+
+ Application
+ MultiByte
+ true
+ v143
+
+
+ Application
+ MultiByte
+ true
+ v143
+
+
+ Application
+ Unicode
+ v143
+
+
+ Application
+ true
+ v143
+
+
+ Application
+ true
+ v143
+
+
+ Application
+ true
+ v143
+
+
+ Application
+ true
+ v143
+
+
+ Application
+ true
+ v143
+
+
+ Application
+ true
+ v143
+
+
+ Application
+ v143
+
+
+ Application
+ v143
+
+
+ Application
+ v143
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ <_ProjectFileVersion>10.0.30128.1
+ x86\TestZlib$(Configuration)\
+ x86\TestZlib$(Configuration)\Tmp\
+ true
+ false
+ x86\TestZlib$(Configuration)\
+ x86\TestZlib$(Configuration)\Tmp\
+ false
+ false
+ x86\TestZlib$(Configuration)\
+ x86\TestZlib$(Configuration)\Tmp\
+ false
+ false
+ x64\TestZlib$(Configuration)\
+ x64\TestZlib$(Configuration)\Tmp\
+ false
+ false
+ false
+ x64\TestZlib$(Configuration)\
+ x64\TestZlib$(Configuration)\Tmp\
+ false
+ false
+ false
+ x64\TestZlib$(Configuration)\
+ x64\TestZlib$(Configuration)\Tmp\
+ false
+ false
+ false
+ AllRules.ruleset
+
+
+ AllRules.ruleset
+ AllRules.ruleset
+ AllRules.ruleset
+
+
+
+
+
+
+ AllRules.ruleset
+
+
+ AllRules.ruleset
+ AllRules.ruleset
+ AllRules.ruleset
+
+
+
+
+
+
+ AllRules.ruleset
+
+
+ AllRules.ruleset
+ AllRules.ruleset
+ AllRules.ruleset
+
+
+
+
+
+
+
+
+ arm64\TestZlib$(Configuration)\
+ arm64\TestZlib$(Configuration)\Tmp\
+
+
+ arm64\TestZlib$(Configuration)\
+ arm64\TestZlib$(Configuration)\Tmp\
+
+
+ arm64\TestZlib$(Configuration)\
+ arm64\TestZlib$(Configuration)\Tmp\
+
+
+ arm\TestZlib$(Configuration)\
+ arm\TestZlib$(Configuration)\Tmp\
+
+
+ arm\TestZlib$(Configuration)\
+ arm\TestZlib$(Configuration)\Tmp\
+
+
+ arm\TestZlib$(Configuration)\
+ arm\TestZlib$(Configuration)\Tmp\
+
+
+
+ Disabled
+ ..\..\..;%(AdditionalIncludeDirectories)
+ WIN32;ZLIB_WINAPI;_DEBUG;_CONSOLE;_CRT_NONSTDC_NO_DEPRECATE;_CRT_SECURE_NO_DEPRECATE;_CRT_NONSTDC_NO_WARNINGS;%(PreprocessorDefinitions)
+ true
+ Default
+ MultiThreadedDebugDLL
+ false
+
+
+ AssemblyAndSourceCode
+ $(IntDir)
+ Level3
+ ProgramDatabase
+
+
+ %(AdditionalDependencies)
+ $(OutDir)testzlib.exe
+ true
+ $(OutDir)testzlib.pdb
+ Console
+ false
+
+
+ MachineX86
+
+
+
+
+ MaxSpeed
+ OnlyExplicitInline
+ true
+ ..\..\..;%(AdditionalIncludeDirectories)
+ WIN32;ZLIB_WINAPI;NDEBUG;_CONSOLE;_CRT_NONSTDC_NO_DEPRECATE;_CRT_SECURE_NO_DEPRECATE;_CRT_NONSTDC_NO_WARNINGS;%(PreprocessorDefinitions)
+ true
+ Default
+ MultiThreaded
+ false
+ true
+
+
+ $(IntDir)
+ Level3
+ ProgramDatabase
+
+
+ $(OutDir)testzlib.exe
+ true
+ Console
+ true
+ true
+ false
+
+
+ MachineX86
+
+
+
+
+ MaxSpeed
+ OnlyExplicitInline
+ true
+ ..\..\..;%(AdditionalIncludeDirectories)
+ WIN32;ZLIB_WINAPI;NDEBUG;_CONSOLE;_CRT_NONSTDC_NO_DEPRECATE;_CRT_SECURE_NO_DEPRECATE;_CRT_NONSTDC_NO_WARNINGS;%(PreprocessorDefinitions)
+ true
+ Default
+ MultiThreaded
+ false
+ true
+
+
+ $(IntDir)
+ Level3
+ ProgramDatabase
+
+
+ %(AdditionalDependencies)
+ $(OutDir)testzlib.exe
+ true
+ Console
+ true
+ true
+ false
+
+
+ MachineX86
+ false
+
+
+
+
+ ..\..\..;%(AdditionalIncludeDirectories)
+ WIN32;ZLIB_WINAPI;_DEBUG;_CONSOLE;_CRT_NONSTDC_NO_DEPRECATE;_CRT_SECURE_NO_DEPRECATE;_CRT_NONSTDC_NO_WARNINGS;%(PreprocessorDefinitions)
+ Default
+ MultiThreadedDebugDLL
+ false
+ $(IntDir)
+
+
+ %(AdditionalDependencies)
+
+
+
+
+ ..\..\..;%(AdditionalIncludeDirectories)
+ WIN32;ZLIB_WINAPI;_DEBUG;_CONSOLE;_CRT_NONSTDC_NO_DEPRECATE;_CRT_SECURE_NO_DEPRECATE;_CRT_NONSTDC_NO_WARNINGS;%(PreprocessorDefinitions)
+ Default
+ MultiThreadedDebugDLL
+ false
+ $(IntDir)
+
+
+ %(AdditionalDependencies)
+
+
+
+
+ ..\..\..;%(AdditionalIncludeDirectories)
+ WIN32;ZLIB_WINAPI;_DEBUG;_CONSOLE;_CRT_NONSTDC_NO_DEPRECATE;_CRT_SECURE_NO_DEPRECATE;_CRT_NONSTDC_NO_WARNINGS;%(PreprocessorDefinitions)
+ Default
+ MultiThreadedDebugDLL
+ false
+ $(IntDir)
+
+
+ %(AdditionalDependencies)
+
+
+
+
+ ..\..\..;%(AdditionalIncludeDirectories)
+ WIN32;ZLIB_WINAPI;NDEBUG;_CONSOLE;_CRT_NONSTDC_NO_DEPRECATE;_CRT_SECURE_NO_DEPRECATE;_CRT_NONSTDC_NO_WARNINGS;%(PreprocessorDefinitions)
+ Default
+ MultiThreadedDLL
+ false
+ $(IntDir)
+
+
+ %(AdditionalDependencies)
+
+
+
+
+ ..\..\..;%(AdditionalIncludeDirectories)
+ WIN32;ZLIB_WINAPI;NDEBUG;_CONSOLE;_CRT_NONSTDC_NO_DEPRECATE;_CRT_SECURE_NO_DEPRECATE;_CRT_NONSTDC_NO_WARNINGS;%(PreprocessorDefinitions)
+ Default
+ MultiThreadedDLL
+ false
+ $(IntDir)
+
+
+ %(AdditionalDependencies)
+
+
+
+
+ ..\..\..;%(AdditionalIncludeDirectories)
+ WIN32;ZLIB_WINAPI;NDEBUG;_CONSOLE;_CRT_NONSTDC_NO_DEPRECATE;_CRT_SECURE_NO_DEPRECATE;_CRT_NONSTDC_NO_WARNINGS;%(PreprocessorDefinitions)
+ Default
+ MultiThreadedDLL
+ false
+ $(IntDir)
+
+
+ %(AdditionalDependencies)
+
+
+
+
+ ..\..\..;%(AdditionalIncludeDirectories)
+ WIN32;ZLIB_WINAPI;NDEBUG;_CONSOLE;_CRT_NONSTDC_NO_DEPRECATE;_CRT_SECURE_NO_DEPRECATE;_CRT_NONSTDC_NO_WARNINGS;%(PreprocessorDefinitions)
+ Default
+ MultiThreadedDLL
+ false
+ $(IntDir)
+
+
+ %(AdditionalDependencies)
+
+
+
+
+ ..\..\..;%(AdditionalIncludeDirectories)
+ WIN32;ZLIB_WINAPI;NDEBUG;_CONSOLE;_CRT_NONSTDC_NO_DEPRECATE;_CRT_SECURE_NO_DEPRECATE;_CRT_NONSTDC_NO_WARNINGS;%(PreprocessorDefinitions)
+ Default
+ MultiThreadedDLL
+ false
+ $(IntDir)
+
+
+ %(AdditionalDependencies)
+
+
+
+
+ ..\..\..;%(AdditionalIncludeDirectories)
+ WIN32;ZLIB_WINAPI;NDEBUG;_CONSOLE;_CRT_NONSTDC_NO_DEPRECATE;_CRT_SECURE_NO_DEPRECATE;_CRT_NONSTDC_NO_WARNINGS;%(PreprocessorDefinitions)
+ Default
+ MultiThreadedDLL
+ false
+ $(IntDir)
+
+
+ %(AdditionalDependencies)
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/src/deps/src/zlib/contrib/vstudio/vc17/testzlibdll.vcxproj b/src/deps/src/zlib/contrib/vstudio/vc17/testzlibdll.vcxproj
new file mode 100644
index 000000000..73bba55da
--- /dev/null
+++ b/src/deps/src/zlib/contrib/vstudio/vc17/testzlibdll.vcxproj
@@ -0,0 +1,409 @@
+
+
+
+
+ Debug
+ ARM
+
+
+ Debug
+ ARM64
+
+
+ Debug
+ Win32
+
+
+ Debug
+ x64
+
+
+ Release
+ ARM
+
+
+ Release
+ ARM64
+
+
+ Release
+ Win32
+
+
+ Release
+ x64
+
+
+
+ {C52F9E7B-498A-42BE-8DB4-85A15694366A}
+ Win32Proj
+ 10.0
+
+
+
+ Application
+ MultiByte
+ v143
+
+
+ Application
+ Unicode
+ v143
+
+
+ Application
+ MultiByte
+ v143
+
+
+ Application
+ MultiByte
+ v143
+
+
+ Application
+ MultiByte
+ v143
+
+
+ Application
+ MultiByte
+ v143
+
+
+ Application
+ MultiByte
+ v143
+
+
+ Application
+ MultiByte
+ v143
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ <_ProjectFileVersion>10.0.30128.1
+ x86\TestZlibDll$(Configuration)\
+ x86\TestZlibDll$(Configuration)\Tmp\
+ true
+ false
+ x86\TestZlibDll$(Configuration)\
+ x86\TestZlibDll$(Configuration)\Tmp\
+ false
+ false
+ x64\TestZlibDll$(Configuration)\
+ x64\TestZlibDll$(Configuration)\Tmp\
+ true
+ true
+ true
+ false
+ false
+ false
+ x64\TestZlibDll$(Configuration)\
+ x64\TestZlibDll$(Configuration)\Tmp\
+ false
+ false
+ false
+ false
+ false
+ false
+ AllRules.ruleset
+
+
+ AllRules.ruleset
+ AllRules.ruleset
+ AllRules.ruleset
+
+
+
+
+
+
+ AllRules.ruleset
+
+
+ AllRules.ruleset
+ AllRules.ruleset
+ AllRules.ruleset
+
+
+
+
+
+
+
+
+ arm64\TestZlibDll$(Configuration)\
+ arm64\TestZlibDll$(Configuration)\Tmp\
+
+
+ arm64\TestZlibDll$(Configuration)\
+ arm64\TestZlibDll$(Configuration)\Tmp\
+
+
+ arm\TestZlibDll$(Configuration)\
+ arm\TestZlibDll$(Configuration)\Tmp\
+
+
+ arm\TestZlibDll$(Configuration)\
+ arm\TestZlibDll$(Configuration)\Tmp\
+
+
+
+ Disabled
+ ..\..\..;..\..\minizip;%(AdditionalIncludeDirectories)
+ WIN32;_CRT_NONSTDC_NO_DEPRECATE;_CRT_SECURE_NO_DEPRECATE;ZLIB_WINAPI;_DEBUG;_CONSOLE;%(PreprocessorDefinitions)
+ true
+ Default
+ MultiThreadedDebugDLL
+ false
+
+
+ $(IntDir)
+ Level3
+ ProgramDatabase
+
+
+ x86\ZlibDllDebug\zlibwapi.lib;%(AdditionalDependencies)
+ $(OutDir)testzlibdll.exe
+ true
+ $(OutDir)testzlib.pdb
+ Console
+ false
+
+
+ MachineX86
+
+
+
+
+ MaxSpeed
+ OnlyExplicitInline
+ true
+ ..\..\..;..\..\minizip;%(AdditionalIncludeDirectories)
+ WIN32;_CRT_NONSTDC_NO_DEPRECATE;_CRT_SECURE_NO_DEPRECATE;ZLIB_WINAPI;NDEBUG;_CONSOLE;%(PreprocessorDefinitions)
+ true
+ Default
+ MultiThreaded
+ false
+ true
+
+
+ $(IntDir)
+ Level3
+ ProgramDatabase
+
+
+ x86\ZlibDllRelease\zlibwapi.lib;%(AdditionalDependencies)
+ $(OutDir)testzlibdll.exe
+ true
+ Console
+ true
+ true
+ false
+
+
+ MachineX86
+
+
+
+
+ X64
+
+
+ Disabled
+ ..\..\..;..\..\minizip;%(AdditionalIncludeDirectories)
+ _CRT_NONSTDC_NO_DEPRECATE;_CRT_SECURE_NO_DEPRECATE;ZLIB_WINAPI;_DEBUG;_CONSOLE;WIN64;%(PreprocessorDefinitions)
+ true
+ Default
+ MultiThreadedDebugDLL
+ false
+
+
+ $(IntDir)
+ Level3
+ ProgramDatabase
+
+
+ x64\ZlibDllDebug\zlibwapi.lib;%(AdditionalDependencies)
+ $(OutDir)testzlibdll.exe
+ true
+ $(OutDir)testzlib.pdb
+ Console
+ MachineX64
+
+
+
+
+
+ Disabled
+ ..\..\..;..\..\minizip;%(AdditionalIncludeDirectories)
+ _CRT_NONSTDC_NO_DEPRECATE;_CRT_SECURE_NO_DEPRECATE;ZLIB_WINAPI;_DEBUG;_CONSOLE;WIN64;%(PreprocessorDefinitions)
+ true
+ Default
+ MultiThreadedDebugDLL
+ false
+
+
+ $(IntDir)
+ Level3
+ ProgramDatabase
+
+
+ x64\ZlibDllDebug\zlibwapi.lib;%(AdditionalDependencies)
+ $(OutDir)testzlibdll.exe
+ true
+ $(OutDir)testzlib.pdb
+ Console
+
+
+
+
+
+ Disabled
+ ..\..\..;..\..\minizip;%(AdditionalIncludeDirectories)
+ _CRT_NONSTDC_NO_DEPRECATE;_CRT_SECURE_NO_DEPRECATE;ZLIB_WINAPI;_DEBUG;_CONSOLE;WIN64;%(PreprocessorDefinitions)
+ true
+ Default
+ MultiThreadedDebugDLL
+ false
+
+
+ $(IntDir)
+ Level3
+ ProgramDatabase
+
+
+ x64\ZlibDllDebug\zlibwapi.lib;%(AdditionalDependencies)
+ $(OutDir)testzlibdll.exe
+ true
+ $(OutDir)testzlib.pdb
+ Console
+
+
+
+
+ X64
+
+
+ MaxSpeed
+ OnlyExplicitInline
+ true
+ ..\..\..;..\..\minizip;%(AdditionalIncludeDirectories)
+ _CRT_NONSTDC_NO_DEPRECATE;_CRT_SECURE_NO_DEPRECATE;ZLIB_WINAPI;NDEBUG;_CONSOLE;WIN64;%(PreprocessorDefinitions)
+ true
+ Default
+ MultiThreadedDLL
+ false
+ true
+
+
+ $(IntDir)
+ Level3
+ ProgramDatabase
+
+
+ x64\ZlibDllRelease\zlibwapi.lib;%(AdditionalDependencies)
+ $(OutDir)testzlibdll.exe
+ true
+ Console
+ true
+ true
+ MachineX64
+
+
+
+
+
+ MaxSpeed
+ OnlyExplicitInline
+ true
+ ..\..\..;..\..\minizip;%(AdditionalIncludeDirectories)
+ _CRT_NONSTDC_NO_DEPRECATE;_CRT_SECURE_NO_DEPRECATE;ZLIB_WINAPI;NDEBUG;_CONSOLE;WIN64;%(PreprocessorDefinitions)
+ true
+ Default
+ MultiThreadedDLL
+ false
+ true
+
+
+ $(IntDir)
+ Level3
+ ProgramDatabase
+
+
+ x64\ZlibDllRelease\zlibwapi.lib;%(AdditionalDependencies)
+ $(OutDir)testzlibdll.exe
+ true
+ Console
+ true
+ true
+
+
+
+
+
+ MaxSpeed
+ OnlyExplicitInline
+ true
+ ..\..\..;..\..\minizip;%(AdditionalIncludeDirectories)
+ _CRT_NONSTDC_NO_DEPRECATE;_CRT_SECURE_NO_DEPRECATE;ZLIB_WINAPI;NDEBUG;_CONSOLE;WIN64;%(PreprocessorDefinitions)
+ true
+ Default
+ MultiThreadedDLL
+ false
+ true
+
+
+ $(IntDir)
+ Level3
+ ProgramDatabase
+
+
+ x64\ZlibDllRelease\zlibwapi.lib;%(AdditionalDependencies)
+ $(OutDir)testzlibdll.exe
+ true
+ Console
+ true
+ true
+
+
+
+
+
+
+
+ {8fd826f8-3739-44e6-8cc8-997122e53b8d}
+
+
+
+
+
+
\ No newline at end of file
diff --git a/src/deps/src/zlib/contrib/vstudio/vc17/zlib.rc b/src/deps/src/zlib/contrib/vstudio/vc17/zlib.rc
new file mode 100644
index 000000000..a55f341c7
--- /dev/null
+++ b/src/deps/src/zlib/contrib/vstudio/vc17/zlib.rc
@@ -0,0 +1,32 @@
+#include
+
+#define IDR_VERSION1 1
+IDR_VERSION1 VERSIONINFO MOVEABLE IMPURE LOADONCALL DISCARDABLE
+ FILEVERSION 1, 3, 1, 0
+ PRODUCTVERSION 1, 3, 1, 0
+ FILEFLAGSMASK VS_FFI_FILEFLAGSMASK
+ FILEFLAGS 0
+ FILEOS VOS_DOS_WINDOWS32
+ FILETYPE VFT_DLL
+ FILESUBTYPE 0 // not used
+BEGIN
+ BLOCK "StringFileInfo"
+ BEGIN
+ BLOCK "040904E4"
+ //language ID = U.S. English, char set = Windows, Multilingual
+
+ BEGIN
+ VALUE "FileDescription", "zlib data compression and ZIP file I/O library\0"
+ VALUE "FileVersion", "1.3.1\0"
+ VALUE "InternalName", "zlib\0"
+ VALUE "OriginalFilename", "zlibwapi.dll\0"
+ VALUE "ProductName", "ZLib.DLL\0"
+ VALUE "Comments","DLL support by Alessandro Iacopetti & Gilles Vollant\0"
+ VALUE "LegalCopyright", "(C) 1995-2024 Jean-loup Gailly & Mark Adler\0"
+ END
+ END
+ BLOCK "VarFileInfo"
+ BEGIN
+ VALUE "Translation", 0x0409, 1252
+ END
+END
diff --git a/src/deps/src/zlib/contrib/vstudio/vc17/zlibstat.vcxproj b/src/deps/src/zlib/contrib/vstudio/vc17/zlibstat.vcxproj
new file mode 100644
index 000000000..b946ac2a9
--- /dev/null
+++ b/src/deps/src/zlib/contrib/vstudio/vc17/zlibstat.vcxproj
@@ -0,0 +1,602 @@
+
+
+
+
+ Debug
+ ARM
+
+
+ Debug
+ ARM64
+
+
+ Debug
+ Win32
+
+
+ Debug
+ x64
+
+
+ ReleaseWithoutAsm
+ ARM
+
+
+ ReleaseWithoutAsm
+ ARM64
+
+
+ ReleaseWithoutAsm
+ Win32
+
+
+ ReleaseWithoutAsm
+ x64
+
+
+ Release
+ ARM
+
+
+ Release
+ ARM64
+
+
+ Release
+ Win32
+
+
+ Release
+ x64
+
+
+
+ {745DEC58-EBB3-47A9-A9B8-4C6627C01BF8}
+ 10.0
+
+
+
+ StaticLibrary
+ false
+ v143
+
+
+ StaticLibrary
+ false
+ v143
+
+
+ StaticLibrary
+ false
+ v143
+ Unicode
+
+
+ StaticLibrary
+ false
+ v143
+
+
+ StaticLibrary
+ false
+ v143
+
+
+ StaticLibrary
+ false
+ v143
+
+
+ StaticLibrary
+ false
+ v143
+
+
+ StaticLibrary
+ false
+ v143
+
+
+ StaticLibrary
+ false
+ v143
+
+
+ StaticLibrary
+ false
+ v143
+
+
+ StaticLibrary
+ false
+ v143
+
+
+ StaticLibrary
+ false
+ v143
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ <_ProjectFileVersion>10.0.30128.1
+ x86\ZlibStat$(Configuration)\
+ x86\ZlibStat$(Configuration)\Tmp\
+ x86\ZlibStat$(Configuration)\
+ x86\ZlibStat$(Configuration)\Tmp\
+ x86\ZlibStat$(Configuration)\
+ x86\ZlibStat$(Configuration)\Tmp\
+ x64\ZlibStat$(Configuration)\
+ x64\ZlibStat$(Configuration)\Tmp\
+ x64\ZlibStat$(Configuration)\
+ x64\ZlibStat$(Configuration)\Tmp\
+ x64\ZlibStat$(Configuration)\
+ x64\ZlibStat$(Configuration)\Tmp\
+ AllRules.ruleset
+
+
+ AllRules.ruleset
+ AllRules.ruleset
+ AllRules.ruleset
+
+
+
+
+
+
+ AllRules.ruleset
+
+
+ AllRules.ruleset
+ AllRules.ruleset
+ AllRules.ruleset
+
+
+
+
+
+
+ AllRules.ruleset
+
+
+ AllRules.ruleset
+ AllRules.ruleset
+ AllRules.ruleset
+
+
+
+
+
+
+
+
+ arm64\ZlibStat$(Configuration)\
+ arm64\ZlibStat$(Configuration)\Tmp\
+
+
+ arm64\ZlibStat$(Configuration)\
+ arm64\ZlibStat$(Configuration)\Tmp\
+
+
+ arm64\ZlibStat$(Configuration)\
+ arm64\ZlibStat$(Configuration)\Tmp\
+
+
+ arm\ZlibStat$(Configuration)\
+ arm\ZlibStat$(Configuration)\Tmp\
+
+
+ arm\ZlibStat$(Configuration)\
+ arm\ZlibStat$(Configuration)\Tmp\
+
+
+ arm\ZlibStat$(Configuration)\
+ arm\ZlibStat$(Configuration)\Tmp\
+
+
+
+ Disabled
+ ..\..\..;%(AdditionalIncludeDirectories)
+ WIN32;ZLIB_WINAPI;_CRT_NONSTDC_NO_DEPRECATE;_CRT_SECURE_NO_DEPRECATE;_CRT_NONSTDC_NO_WARNINGS;%(PreprocessorDefinitions)
+
+
+ MultiThreadedDebugDLL
+ false
+ $(IntDir)zlibstat.pch
+ $(IntDir)
+ $(IntDir)
+ $(OutDir)
+ Level3
+ true
+ OldStyle
+
+
+ 0x040c
+
+
+ /MACHINE:X86 /NODEFAULTLIB %(AdditionalOptions)
+ $(OutDir)zlibstat.lib
+ true
+
+
+
+
+ OnlyExplicitInline
+ ..\..\..;%(AdditionalIncludeDirectories)
+ WIN32;ZLIB_WINAPI;_CRT_NONSTDC_NO_DEPRECATE;_CRT_SECURE_NO_DEPRECATE;_CRT_NONSTDC_NO_WARNINGS;%(PreprocessorDefinitions)
+ true
+
+
+ MultiThreaded
+ false
+ true
+ $(IntDir)zlibstat.pch
+ $(IntDir)
+ $(IntDir)
+ $(OutDir)
+ Level3
+ true
+
+
+ 0x040c
+
+
+ /MACHINE:X86 /NODEFAULTLIB %(AdditionalOptions)
+ %(AdditionalDependencies)
+ $(OutDir)zlibstat.lib
+ true
+
+
+
+
+ OnlyExplicitInline
+ ..\..\..;%(AdditionalIncludeDirectories)
+ WIN32;ZLIB_WINAPI;_CRT_NONSTDC_NO_DEPRECATE;_CRT_SECURE_NO_DEPRECATE;_CRT_NONSTDC_NO_WARNINGS;%(PreprocessorDefinitions)
+ true
+
+
+ MultiThreaded
+ false
+ true
+ $(IntDir)zlibstat.pch
+ $(IntDir)
+ $(IntDir)
+ $(OutDir)
+ Level3
+ true
+
+
+ 0x040c
+
+
+ /MACHINE:X86 /NODEFAULTLIB %(AdditionalOptions)
+ $(OutDir)zlibstat.lib
+ true
+
+
+
+
+ X64
+
+
+ Disabled
+ ..\..\..;%(AdditionalIncludeDirectories)
+ ZLIB_WINAPI;_CRT_NONSTDC_NO_DEPRECATE;_CRT_SECURE_NO_DEPRECATE;_CRT_NONSTDC_NO_WARNINGS;WIN64;%(PreprocessorDefinitions)
+
+
+ MultiThreadedDebugDLL
+ false
+ $(IntDir)zlibstat.pch
+ $(IntDir)
+ $(IntDir)
+ $(OutDir)
+ Level3
+ true
+ OldStyle
+
+
+ 0x040c
+
+
+ /MACHINE:AMD64 /NODEFAULTLIB %(AdditionalOptions)
+ $(OutDir)zlibstat.lib
+ true
+
+
+
+
+
+ Disabled
+ ..\..\..;%(AdditionalIncludeDirectories)
+ ZLIB_WINAPI;_CRT_NONSTDC_NO_DEPRECATE;_CRT_SECURE_NO_DEPRECATE;_CRT_NONSTDC_NO_WARNINGS;WIN64;%(PreprocessorDefinitions)
+
+
+ MultiThreadedDebugDLL
+ false
+ $(IntDir)zlibstat.pch
+ $(IntDir)
+ $(IntDir)
+ $(OutDir)
+ Level3
+ true
+ OldStyle
+
+
+ 0x040c
+
+
+ /MACHINE:ARM64 /NODEFAULTLIB %(AdditionalOptions)
+ $(OutDir)zlibstat.lib
+ true
+
+
+
+
+
+ Disabled
+ ..\..\..;%(AdditionalIncludeDirectories)
+ ZLIB_WINAPI;_CRT_NONSTDC_NO_DEPRECATE;_CRT_SECURE_NO_DEPRECATE;_CRT_NONSTDC_NO_WARNINGS;WIN64;%(PreprocessorDefinitions)
+
+
+ MultiThreadedDebugDLL
+ false
+ $(IntDir)zlibstat.pch
+ $(IntDir)
+ $(IntDir)
+ $(OutDir)
+ Level3
+ true
+ OldStyle
+
+
+ 0x040c
+
+
+ /MACHINE:ARM /NODEFAULTLIB %(AdditionalOptions)
+ $(OutDir)zlibstat.lib
+ true
+
+
+
+
+ X64
+
+
+ OnlyExplicitInline
+ ..\..\..;%(AdditionalIncludeDirectories)
+ ZLIB_WINAPI;_CRT_NONSTDC_NO_DEPRECATE;_CRT_SECURE_NO_DEPRECATE;_CRT_NONSTDC_NO_WARNINGS;WIN64;%(PreprocessorDefinitions)
+ true
+
+
+ MultiThreadedDLL
+ false
+ true
+ $(IntDir)zlibstat.pch
+ $(IntDir)
+ $(IntDir)
+ $(OutDir)
+ Level3
+ true
+
+
+ 0x040c
+
+
+ /MACHINE:AMD64 /NODEFAULTLIB %(AdditionalOptions)
+ %(AdditionalDependencies)
+ $(OutDir)zlibstat.lib
+ true
+
+
+
+
+
+ OnlyExplicitInline
+ ..\..\..;%(AdditionalIncludeDirectories)
+ ZLIB_WINAPI;_CRT_NONSTDC_NO_DEPRECATE;_CRT_SECURE_NO_DEPRECATE;_CRT_NONSTDC_NO_WARNINGS;WIN64;%(PreprocessorDefinitions)
+ true
+
+
+ MultiThreadedDLL
+ false
+ true
+ $(IntDir)zlibstat.pch
+ $(IntDir)
+ $(IntDir)
+ $(OutDir)
+ Level3
+ true
+
+
+ 0x040c
+
+
+ /MACHINE:ARM64 /NODEFAULTLIB %(AdditionalOptions)
+ %(AdditionalDependencies)
+ $(OutDir)zlibstat.lib
+ true
+
+
+
+
+
+ OnlyExplicitInline
+ ..\..\..;%(AdditionalIncludeDirectories)
+ ZLIB_WINAPI;_CRT_NONSTDC_NO_DEPRECATE;_CRT_SECURE_NO_DEPRECATE;_CRT_NONSTDC_NO_WARNINGS;WIN64;%(PreprocessorDefinitions)
+ true
+
+
+ MultiThreadedDLL
+ false
+ true
+ $(IntDir)zlibstat.pch
+ $(IntDir)
+ $(IntDir)
+ $(OutDir)
+ Level3
+ true
+
+
+ 0x040c
+
+
+ /MACHINE:ARM /NODEFAULTLIB %(AdditionalOptions)
+ %(AdditionalDependencies)
+ $(OutDir)zlibstat.lib
+ true
+
+
+
+
+ X64
+
+
+ OnlyExplicitInline
+ ..\..\..;%(AdditionalIncludeDirectories)
+ ZLIB_WINAPI;_CRT_NONSTDC_NO_DEPRECATE;_CRT_SECURE_NO_DEPRECATE;_CRT_NONSTDC_NO_WARNINGS;WIN64;%(PreprocessorDefinitions)
+ true
+
+
+ MultiThreadedDLL
+ false
+ true
+ $(IntDir)zlibstat.pch
+ $(IntDir)
+ $(IntDir)
+ $(OutDir)
+ Level3
+ true
+
+
+ 0x040c
+
+
+ /MACHINE:AMD64 /NODEFAULTLIB %(AdditionalOptions)
+ $(OutDir)zlibstat.lib
+ true
+
+
+
+
+
+ OnlyExplicitInline
+ ..\..\..;%(AdditionalIncludeDirectories)
+ ZLIB_WINAPI;_CRT_NONSTDC_NO_DEPRECATE;_CRT_SECURE_NO_DEPRECATE;_CRT_NONSTDC_NO_WARNINGS;WIN64;%(PreprocessorDefinitions)
+ true
+
+
+ MultiThreadedDLL
+ false
+ true
+ $(IntDir)zlibstat.pch
+ $(IntDir)
+ $(IntDir)
+ $(OutDir)
+ Level3
+ true
+
+
+ 0x040c
+
+
+ /MACHINE:ARM64 /NODEFAULTLIB %(AdditionalOptions)
+ $(OutDir)zlibstat.lib
+ true
+
+
+
+
+
+ OnlyExplicitInline
+ ..\..\..;%(AdditionalIncludeDirectories)
+ ZLIB_WINAPI;_CRT_NONSTDC_NO_DEPRECATE;_CRT_SECURE_NO_DEPRECATE;_CRT_NONSTDC_NO_WARNINGS;WIN64;%(PreprocessorDefinitions)
+ true
+
+
+ MultiThreadedDLL
+ false
+ true
+ $(IntDir)zlibstat.pch
+ $(IntDir)
+ $(IntDir)
+ $(OutDir)
+ Level3
+ true
+
+
+ 0x040c
+
+
+ /MACHINE:ARM /NODEFAULTLIB %(AdditionalOptions)
+ $(OutDir)zlibstat.lib
+ true
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/src/deps/src/zlib/contrib/vstudio/vc17/zlibvc.def b/src/deps/src/zlib/contrib/vstudio/vc17/zlibvc.def
new file mode 100644
index 000000000..53947cc31
--- /dev/null
+++ b/src/deps/src/zlib/contrib/vstudio/vc17/zlibvc.def
@@ -0,0 +1,158 @@
+LIBRARY
+; zlib data compression and ZIP file I/O library
+
+VERSION 1.3.1
+
+EXPORTS
+ adler32 @1
+ compress @2
+ crc32 @3
+ deflate @4
+ deflateCopy @5
+ deflateEnd @6
+ deflateInit2_ @7
+ deflateInit_ @8
+ deflateParams @9
+ deflateReset @10
+ deflateSetDictionary @11
+ gzclose @12
+ gzdopen @13
+ gzerror @14
+ gzflush @15
+ gzopen @16
+ gzread @17
+ gzwrite @18
+ inflate @19
+ inflateEnd @20
+ inflateInit2_ @21
+ inflateInit_ @22
+ inflateReset @23
+ inflateSetDictionary @24
+ inflateSync @25
+ uncompress @26
+ zlibVersion @27
+ gzprintf @28
+ gzputc @29
+ gzgetc @30
+ gzseek @31
+ gzrewind @32
+ gztell @33
+ gzeof @34
+ gzsetparams @35
+ zError @36
+ inflateSyncPoint @37
+ get_crc_table @38
+ compress2 @39
+ gzputs @40
+ gzgets @41
+ inflateCopy @42
+ inflateBackInit_ @43
+ inflateBack @44
+ inflateBackEnd @45
+ compressBound @46
+ deflateBound @47
+ gzclearerr @48
+ gzungetc @49
+ zlibCompileFlags @50
+ deflatePrime @51
+ deflatePending @52
+
+ unzOpen @61
+ unzClose @62
+ unzGetGlobalInfo @63
+ unzGetCurrentFileInfo @64
+ unzGoToFirstFile @65
+ unzGoToNextFile @66
+ unzOpenCurrentFile @67
+ unzReadCurrentFile @68
+ unzOpenCurrentFile3 @69
+ unztell @70
+ unzeof @71
+ unzCloseCurrentFile @72
+ unzGetGlobalComment @73
+ unzStringFileNameCompare @74
+ unzLocateFile @75
+ unzGetLocalExtrafield @76
+ unzOpen2 @77
+ unzOpenCurrentFile2 @78
+ unzOpenCurrentFilePassword @79
+
+ zipOpen @80
+ zipOpenNewFileInZip @81
+ zipWriteInFileInZip @82
+ zipCloseFileInZip @83
+ zipClose @84
+ zipOpenNewFileInZip2 @86
+ zipCloseFileInZipRaw @87
+ zipOpen2 @88
+ zipOpenNewFileInZip3 @89
+
+ unzGetFilePos @100
+ unzGoToFilePos @101
+
+ fill_win32_filefunc @110
+
+; zlibwapi v1.2.4 added:
+ fill_win32_filefunc64 @111
+ fill_win32_filefunc64A @112
+ fill_win32_filefunc64W @113
+
+ unzOpen64 @120
+ unzOpen2_64 @121
+ unzGetGlobalInfo64 @122
+ unzGetCurrentFileInfo64 @124
+ unzGetCurrentFileZStreamPos64 @125
+ unztell64 @126
+ unzGetFilePos64 @127
+ unzGoToFilePos64 @128
+
+ zipOpen64 @130
+ zipOpen2_64 @131
+ zipOpenNewFileInZip64 @132
+ zipOpenNewFileInZip2_64 @133
+ zipOpenNewFileInZip3_64 @134
+ zipOpenNewFileInZip4_64 @135
+ zipCloseFileInZipRaw64 @136
+
+; zlib1 v1.2.4 added:
+ adler32_combine @140
+ crc32_combine @142
+ deflateSetHeader @144
+ deflateTune @145
+ gzbuffer @146
+ gzclose_r @147
+ gzclose_w @148
+ gzdirect @149
+ gzoffset @150
+ inflateGetHeader @156
+ inflateMark @157
+ inflatePrime @158
+ inflateReset2 @159
+ inflateUndermine @160
+
+; zlib1 v1.2.6 added:
+ gzgetc_ @161
+ inflateResetKeep @163
+ deflateResetKeep @164
+
+; zlib1 v1.2.7 added:
+ gzopen_w @165
+
+; zlib1 v1.2.8 added:
+ inflateGetDictionary @166
+ gzvprintf @167
+
+; zlib1 v1.2.9 added:
+ inflateCodesUsed @168
+ inflateValidate @169
+ uncompress2 @170
+ gzfread @171
+ gzfwrite @172
+ deflateGetDictionary @173
+ adler32_z @174
+ crc32_z @175
+
+; zlib1 v1.2.12 added:
+ crc32_combine_gen @176
+ crc32_combine_gen64 @177
+ crc32_combine_op @178
diff --git a/src/deps/src/zlib/contrib/vstudio/vc17/zlibvc.sln b/src/deps/src/zlib/contrib/vstudio/vc17/zlibvc.sln
new file mode 100644
index 000000000..67896b747
--- /dev/null
+++ b/src/deps/src/zlib/contrib/vstudio/vc17/zlibvc.sln
@@ -0,0 +1,179 @@
+
+Microsoft Visual Studio Solution File, Format Version 12.00
+# Visual Studio Version 17
+VisualStudioVersion = 17.4.33015.44
+MinimumVisualStudioVersion = 10.0.40219.1
+Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "zlibvc", "zlibvc.vcxproj", "{8FD826F8-3739-44E6-8CC8-997122E53B8D}"
+EndProject
+Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "zlibstat", "zlibstat.vcxproj", "{745DEC58-EBB3-47A9-A9B8-4C6627C01BF8}"
+EndProject
+Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "testzlib", "testzlib.vcxproj", "{AA6666AA-E09F-4135-9C0C-4FE50C3C654B}"
+EndProject
+Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "testzlibdll", "testzlibdll.vcxproj", "{C52F9E7B-498A-42BE-8DB4-85A15694366A}"
+EndProject
+Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "minizip", "minizip.vcxproj", "{48CDD9DC-E09F-4135-9C0C-4FE50C3C654B}"
+EndProject
+Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "miniunz", "miniunz.vcxproj", "{C52F9E7B-498A-42BE-8DB4-85A15694382A}"
+EndProject
+Global
+ GlobalSection(SolutionConfigurationPlatforms) = preSolution
+ Debug|ARM = Debug|ARM
+ Debug|ARM64 = Debug|ARM64
+ Debug|Win32 = Debug|Win32
+ Debug|x64 = Debug|x64
+ Release|ARM = Release|ARM
+ Release|ARM64 = Release|ARM64
+ Release|Win32 = Release|Win32
+ Release|x64 = Release|x64
+ ReleaseWithoutAsm|ARM = ReleaseWithoutAsm|ARM
+ ReleaseWithoutAsm|ARM64 = ReleaseWithoutAsm|ARM64
+ ReleaseWithoutAsm|Win32 = ReleaseWithoutAsm|Win32
+ ReleaseWithoutAsm|x64 = ReleaseWithoutAsm|x64
+ EndGlobalSection
+ GlobalSection(ProjectConfigurationPlatforms) = postSolution
+ {8FD826F8-3739-44E6-8CC8-997122E53B8D}.Debug|ARM.ActiveCfg = Debug|ARM
+ {8FD826F8-3739-44E6-8CC8-997122E53B8D}.Debug|ARM.Build.0 = Debug|ARM
+ {8FD826F8-3739-44E6-8CC8-997122E53B8D}.Debug|ARM64.ActiveCfg = Debug|ARM64
+ {8FD826F8-3739-44E6-8CC8-997122E53B8D}.Debug|ARM64.Build.0 = Debug|ARM64
+ {8FD826F8-3739-44E6-8CC8-997122E53B8D}.Debug|Win32.ActiveCfg = Debug|Win32
+ {8FD826F8-3739-44E6-8CC8-997122E53B8D}.Debug|Win32.Build.0 = Debug|Win32
+ {8FD826F8-3739-44E6-8CC8-997122E53B8D}.Debug|x64.ActiveCfg = Debug|x64
+ {8FD826F8-3739-44E6-8CC8-997122E53B8D}.Debug|x64.Build.0 = Debug|x64
+ {8FD826F8-3739-44E6-8CC8-997122E53B8D}.Release|ARM.ActiveCfg = Release|ARM
+ {8FD826F8-3739-44E6-8CC8-997122E53B8D}.Release|ARM.Build.0 = Release|ARM
+ {8FD826F8-3739-44E6-8CC8-997122E53B8D}.Release|ARM64.ActiveCfg = Release|ARM64
+ {8FD826F8-3739-44E6-8CC8-997122E53B8D}.Release|ARM64.Build.0 = Release|ARM64
+ {8FD826F8-3739-44E6-8CC8-997122E53B8D}.Release|Win32.ActiveCfg = Release|Win32
+ {8FD826F8-3739-44E6-8CC8-997122E53B8D}.Release|Win32.Build.0 = Release|Win32
+ {8FD826F8-3739-44E6-8CC8-997122E53B8D}.Release|x64.ActiveCfg = Release|x64
+ {8FD826F8-3739-44E6-8CC8-997122E53B8D}.Release|x64.Build.0 = Release|x64
+ {8FD826F8-3739-44E6-8CC8-997122E53B8D}.ReleaseWithoutAsm|ARM.ActiveCfg = ReleaseWithoutAsm|ARM
+ {8FD826F8-3739-44E6-8CC8-997122E53B8D}.ReleaseWithoutAsm|ARM.Build.0 = ReleaseWithoutAsm|ARM
+ {8FD826F8-3739-44E6-8CC8-997122E53B8D}.ReleaseWithoutAsm|ARM64.ActiveCfg = ReleaseWithoutAsm|ARM64
+ {8FD826F8-3739-44E6-8CC8-997122E53B8D}.ReleaseWithoutAsm|ARM64.Build.0 = ReleaseWithoutAsm|ARM64
+ {8FD826F8-3739-44E6-8CC8-997122E53B8D}.ReleaseWithoutAsm|Win32.ActiveCfg = ReleaseWithoutAsm|Win32
+ {8FD826F8-3739-44E6-8CC8-997122E53B8D}.ReleaseWithoutAsm|Win32.Build.0 = ReleaseWithoutAsm|Win32
+ {8FD826F8-3739-44E6-8CC8-997122E53B8D}.ReleaseWithoutAsm|x64.ActiveCfg = ReleaseWithoutAsm|x64
+ {8FD826F8-3739-44E6-8CC8-997122E53B8D}.ReleaseWithoutAsm|x64.Build.0 = ReleaseWithoutAsm|x64
+ {745DEC58-EBB3-47A9-A9B8-4C6627C01BF8}.Debug|ARM.ActiveCfg = Debug|ARM
+ {745DEC58-EBB3-47A9-A9B8-4C6627C01BF8}.Debug|ARM.Build.0 = Debug|ARM
+ {745DEC58-EBB3-47A9-A9B8-4C6627C01BF8}.Debug|ARM64.ActiveCfg = Debug|ARM64
+ {745DEC58-EBB3-47A9-A9B8-4C6627C01BF8}.Debug|ARM64.Build.0 = Debug|ARM64
+ {745DEC58-EBB3-47A9-A9B8-4C6627C01BF8}.Debug|Win32.ActiveCfg = Debug|Win32
+ {745DEC58-EBB3-47A9-A9B8-4C6627C01BF8}.Debug|Win32.Build.0 = Debug|Win32
+ {745DEC58-EBB3-47A9-A9B8-4C6627C01BF8}.Debug|x64.ActiveCfg = Debug|x64
+ {745DEC58-EBB3-47A9-A9B8-4C6627C01BF8}.Debug|x64.Build.0 = Debug|x64
+ {745DEC58-EBB3-47A9-A9B8-4C6627C01BF8}.Release|ARM.ActiveCfg = Release|ARM
+ {745DEC58-EBB3-47A9-A9B8-4C6627C01BF8}.Release|ARM.Build.0 = Release|ARM
+ {745DEC58-EBB3-47A9-A9B8-4C6627C01BF8}.Release|ARM64.ActiveCfg = Release|ARM64
+ {745DEC58-EBB3-47A9-A9B8-4C6627C01BF8}.Release|ARM64.Build.0 = Release|ARM64
+ {745DEC58-EBB3-47A9-A9B8-4C6627C01BF8}.Release|Win32.ActiveCfg = Release|Win32
+ {745DEC58-EBB3-47A9-A9B8-4C6627C01BF8}.Release|Win32.Build.0 = Release|Win32
+ {745DEC58-EBB3-47A9-A9B8-4C6627C01BF8}.Release|x64.ActiveCfg = Release|x64
+ {745DEC58-EBB3-47A9-A9B8-4C6627C01BF8}.Release|x64.Build.0 = Release|x64
+ {745DEC58-EBB3-47A9-A9B8-4C6627C01BF8}.ReleaseWithoutAsm|ARM.ActiveCfg = ReleaseWithoutAsm|ARM
+ {745DEC58-EBB3-47A9-A9B8-4C6627C01BF8}.ReleaseWithoutAsm|ARM.Build.0 = ReleaseWithoutAsm|ARM
+ {745DEC58-EBB3-47A9-A9B8-4C6627C01BF8}.ReleaseWithoutAsm|ARM64.ActiveCfg = ReleaseWithoutAsm|ARM64
+ {745DEC58-EBB3-47A9-A9B8-4C6627C01BF8}.ReleaseWithoutAsm|ARM64.Build.0 = ReleaseWithoutAsm|ARM64
+ {745DEC58-EBB3-47A9-A9B8-4C6627C01BF8}.ReleaseWithoutAsm|Win32.ActiveCfg = ReleaseWithoutAsm|Win32
+ {745DEC58-EBB3-47A9-A9B8-4C6627C01BF8}.ReleaseWithoutAsm|Win32.Build.0 = ReleaseWithoutAsm|Win32
+ {745DEC58-EBB3-47A9-A9B8-4C6627C01BF8}.ReleaseWithoutAsm|x64.ActiveCfg = ReleaseWithoutAsm|x64
+ {745DEC58-EBB3-47A9-A9B8-4C6627C01BF8}.ReleaseWithoutAsm|x64.Build.0 = ReleaseWithoutAsm|x64
+ {AA6666AA-E09F-4135-9C0C-4FE50C3C654B}.Debug|ARM.ActiveCfg = Debug|ARM
+ {AA6666AA-E09F-4135-9C0C-4FE50C3C654B}.Debug|ARM.Build.0 = Debug|ARM
+ {AA6666AA-E09F-4135-9C0C-4FE50C3C654B}.Debug|ARM64.ActiveCfg = Debug|ARM64
+ {AA6666AA-E09F-4135-9C0C-4FE50C3C654B}.Debug|ARM64.Build.0 = Debug|ARM64
+ {AA6666AA-E09F-4135-9C0C-4FE50C3C654B}.Debug|Win32.ActiveCfg = Debug|Win32
+ {AA6666AA-E09F-4135-9C0C-4FE50C3C654B}.Debug|Win32.Build.0 = Debug|Win32
+ {AA6666AA-E09F-4135-9C0C-4FE50C3C654B}.Debug|x64.ActiveCfg = Debug|x64
+ {AA6666AA-E09F-4135-9C0C-4FE50C3C654B}.Debug|x64.Build.0 = Debug|x64
+ {AA6666AA-E09F-4135-9C0C-4FE50C3C654B}.Release|ARM.ActiveCfg = Release|ARM
+ {AA6666AA-E09F-4135-9C0C-4FE50C3C654B}.Release|ARM.Build.0 = Release|ARM
+ {AA6666AA-E09F-4135-9C0C-4FE50C3C654B}.Release|ARM64.ActiveCfg = Release|ARM64
+ {AA6666AA-E09F-4135-9C0C-4FE50C3C654B}.Release|ARM64.Build.0 = Release|ARM64
+ {AA6666AA-E09F-4135-9C0C-4FE50C3C654B}.Release|Win32.ActiveCfg = Release|Win32
+ {AA6666AA-E09F-4135-9C0C-4FE50C3C654B}.Release|Win32.Build.0 = Release|Win32
+ {AA6666AA-E09F-4135-9C0C-4FE50C3C654B}.Release|x64.ActiveCfg = Release|x64
+ {AA6666AA-E09F-4135-9C0C-4FE50C3C654B}.Release|x64.Build.0 = Release|x64
+ {AA6666AA-E09F-4135-9C0C-4FE50C3C654B}.ReleaseWithoutAsm|ARM.ActiveCfg = ReleaseWithoutAsm|ARM
+ {AA6666AA-E09F-4135-9C0C-4FE50C3C654B}.ReleaseWithoutAsm|ARM.Build.0 = ReleaseWithoutAsm|ARM
+ {AA6666AA-E09F-4135-9C0C-4FE50C3C654B}.ReleaseWithoutAsm|ARM64.ActiveCfg = ReleaseWithoutAsm|ARM64
+ {AA6666AA-E09F-4135-9C0C-4FE50C3C654B}.ReleaseWithoutAsm|ARM64.Build.0 = ReleaseWithoutAsm|ARM64
+ {AA6666AA-E09F-4135-9C0C-4FE50C3C654B}.ReleaseWithoutAsm|Win32.ActiveCfg = ReleaseWithoutAsm|Win32
+ {AA6666AA-E09F-4135-9C0C-4FE50C3C654B}.ReleaseWithoutAsm|Win32.Build.0 = ReleaseWithoutAsm|Win32
+ {AA6666AA-E09F-4135-9C0C-4FE50C3C654B}.ReleaseWithoutAsm|x64.ActiveCfg = ReleaseWithoutAsm|x64
+ {AA6666AA-E09F-4135-9C0C-4FE50C3C654B}.ReleaseWithoutAsm|x64.Build.0 = ReleaseWithoutAsm|x64
+ {C52F9E7B-498A-42BE-8DB4-85A15694366A}.Debug|ARM.ActiveCfg = Debug|ARM
+ {C52F9E7B-498A-42BE-8DB4-85A15694366A}.Debug|ARM.Build.0 = Debug|ARM
+ {C52F9E7B-498A-42BE-8DB4-85A15694366A}.Debug|ARM64.ActiveCfg = Debug|ARM64
+ {C52F9E7B-498A-42BE-8DB4-85A15694366A}.Debug|ARM64.Build.0 = Debug|ARM64
+ {C52F9E7B-498A-42BE-8DB4-85A15694366A}.Debug|Win32.ActiveCfg = Debug|Win32
+ {C52F9E7B-498A-42BE-8DB4-85A15694366A}.Debug|Win32.Build.0 = Debug|Win32
+ {C52F9E7B-498A-42BE-8DB4-85A15694366A}.Debug|x64.ActiveCfg = Debug|x64
+ {C52F9E7B-498A-42BE-8DB4-85A15694366A}.Debug|x64.Build.0 = Debug|x64
+ {C52F9E7B-498A-42BE-8DB4-85A15694366A}.Release|ARM.ActiveCfg = Release|ARM
+ {C52F9E7B-498A-42BE-8DB4-85A15694366A}.Release|ARM.Build.0 = Release|ARM
+ {C52F9E7B-498A-42BE-8DB4-85A15694366A}.Release|ARM64.ActiveCfg = Release|ARM64
+ {C52F9E7B-498A-42BE-8DB4-85A15694366A}.Release|ARM64.Build.0 = Release|ARM64
+ {C52F9E7B-498A-42BE-8DB4-85A15694366A}.Release|Win32.ActiveCfg = Release|Win32
+ {C52F9E7B-498A-42BE-8DB4-85A15694366A}.Release|Win32.Build.0 = Release|Win32
+ {C52F9E7B-498A-42BE-8DB4-85A15694366A}.Release|x64.ActiveCfg = Release|x64
+ {C52F9E7B-498A-42BE-8DB4-85A15694366A}.Release|x64.Build.0 = Release|x64
+ {C52F9E7B-498A-42BE-8DB4-85A15694366A}.ReleaseWithoutAsm|ARM.ActiveCfg = Release|ARM
+ {C52F9E7B-498A-42BE-8DB4-85A15694366A}.ReleaseWithoutAsm|ARM.Build.0 = Release|ARM
+ {C52F9E7B-498A-42BE-8DB4-85A15694366A}.ReleaseWithoutAsm|ARM64.ActiveCfg = Release|ARM64
+ {C52F9E7B-498A-42BE-8DB4-85A15694366A}.ReleaseWithoutAsm|ARM64.Build.0 = Release|ARM64
+ {C52F9E7B-498A-42BE-8DB4-85A15694366A}.ReleaseWithoutAsm|Win32.ActiveCfg = Release|Win32
+ {C52F9E7B-498A-42BE-8DB4-85A15694366A}.ReleaseWithoutAsm|x64.ActiveCfg = Release|x64
+ {48CDD9DC-E09F-4135-9C0C-4FE50C3C654B}.Debug|ARM.ActiveCfg = Debug|ARM
+ {48CDD9DC-E09F-4135-9C0C-4FE50C3C654B}.Debug|ARM.Build.0 = Debug|ARM
+ {48CDD9DC-E09F-4135-9C0C-4FE50C3C654B}.Debug|ARM64.ActiveCfg = Debug|ARM64
+ {48CDD9DC-E09F-4135-9C0C-4FE50C3C654B}.Debug|ARM64.Build.0 = Debug|ARM64
+ {48CDD9DC-E09F-4135-9C0C-4FE50C3C654B}.Debug|Win32.ActiveCfg = Debug|Win32
+ {48CDD9DC-E09F-4135-9C0C-4FE50C3C654B}.Debug|Win32.Build.0 = Debug|Win32
+ {48CDD9DC-E09F-4135-9C0C-4FE50C3C654B}.Debug|x64.ActiveCfg = Debug|x64
+ {48CDD9DC-E09F-4135-9C0C-4FE50C3C654B}.Debug|x64.Build.0 = Debug|x64
+ {48CDD9DC-E09F-4135-9C0C-4FE50C3C654B}.Release|ARM.ActiveCfg = Release|ARM
+ {48CDD9DC-E09F-4135-9C0C-4FE50C3C654B}.Release|ARM.Build.0 = Release|ARM
+ {48CDD9DC-E09F-4135-9C0C-4FE50C3C654B}.Release|ARM64.ActiveCfg = Release|ARM64
+ {48CDD9DC-E09F-4135-9C0C-4FE50C3C654B}.Release|ARM64.Build.0 = Release|ARM64
+ {48CDD9DC-E09F-4135-9C0C-4FE50C3C654B}.Release|Win32.ActiveCfg = Release|Win32
+ {48CDD9DC-E09F-4135-9C0C-4FE50C3C654B}.Release|Win32.Build.0 = Release|Win32
+ {48CDD9DC-E09F-4135-9C0C-4FE50C3C654B}.Release|x64.ActiveCfg = Release|x64
+ {48CDD9DC-E09F-4135-9C0C-4FE50C3C654B}.Release|x64.Build.0 = Release|x64
+ {48CDD9DC-E09F-4135-9C0C-4FE50C3C654B}.ReleaseWithoutAsm|ARM.ActiveCfg = Release|ARM
+ {48CDD9DC-E09F-4135-9C0C-4FE50C3C654B}.ReleaseWithoutAsm|ARM.Build.0 = Release|ARM
+ {48CDD9DC-E09F-4135-9C0C-4FE50C3C654B}.ReleaseWithoutAsm|ARM64.ActiveCfg = Release|ARM64
+ {48CDD9DC-E09F-4135-9C0C-4FE50C3C654B}.ReleaseWithoutAsm|ARM64.Build.0 = Release|ARM64
+ {48CDD9DC-E09F-4135-9C0C-4FE50C3C654B}.ReleaseWithoutAsm|Win32.ActiveCfg = Release|Win32
+ {48CDD9DC-E09F-4135-9C0C-4FE50C3C654B}.ReleaseWithoutAsm|x64.ActiveCfg = Release|x64
+ {C52F9E7B-498A-42BE-8DB4-85A15694382A}.Debug|ARM.ActiveCfg = Debug|ARM
+ {C52F9E7B-498A-42BE-8DB4-85A15694382A}.Debug|ARM.Build.0 = Debug|ARM
+ {C52F9E7B-498A-42BE-8DB4-85A15694382A}.Debug|ARM64.ActiveCfg = Debug|ARM64
+ {C52F9E7B-498A-42BE-8DB4-85A15694382A}.Debug|ARM64.Build.0 = Debug|ARM64
+ {C52F9E7B-498A-42BE-8DB4-85A15694382A}.Debug|Win32.ActiveCfg = Debug|Win32
+ {C52F9E7B-498A-42BE-8DB4-85A15694382A}.Debug|Win32.Build.0 = Debug|Win32
+ {C52F9E7B-498A-42BE-8DB4-85A15694382A}.Debug|x64.ActiveCfg = Debug|x64
+ {C52F9E7B-498A-42BE-8DB4-85A15694382A}.Debug|x64.Build.0 = Debug|x64
+ {C52F9E7B-498A-42BE-8DB4-85A15694382A}.Release|ARM.ActiveCfg = Release|ARM
+ {C52F9E7B-498A-42BE-8DB4-85A15694382A}.Release|ARM.Build.0 = Release|ARM
+ {C52F9E7B-498A-42BE-8DB4-85A15694382A}.Release|ARM64.ActiveCfg = Release|ARM64
+ {C52F9E7B-498A-42BE-8DB4-85A15694382A}.Release|ARM64.Build.0 = Release|ARM64
+ {C52F9E7B-498A-42BE-8DB4-85A15694382A}.Release|Win32.ActiveCfg = Release|Win32
+ {C52F9E7B-498A-42BE-8DB4-85A15694382A}.Release|Win32.Build.0 = Release|Win32
+ {C52F9E7B-498A-42BE-8DB4-85A15694382A}.Release|x64.ActiveCfg = Release|x64
+ {C52F9E7B-498A-42BE-8DB4-85A15694382A}.Release|x64.Build.0 = Release|x64
+ {C52F9E7B-498A-42BE-8DB4-85A15694382A}.ReleaseWithoutAsm|ARM.ActiveCfg = Release|ARM
+ {C52F9E7B-498A-42BE-8DB4-85A15694382A}.ReleaseWithoutAsm|ARM.Build.0 = Release|ARM
+ {C52F9E7B-498A-42BE-8DB4-85A15694382A}.ReleaseWithoutAsm|ARM64.ActiveCfg = Release|ARM64
+ {C52F9E7B-498A-42BE-8DB4-85A15694382A}.ReleaseWithoutAsm|ARM64.Build.0 = Release|ARM64
+ {C52F9E7B-498A-42BE-8DB4-85A15694382A}.ReleaseWithoutAsm|Win32.ActiveCfg = Release|Win32
+ {C52F9E7B-498A-42BE-8DB4-85A15694382A}.ReleaseWithoutAsm|x64.ActiveCfg = Release|x64
+ EndGlobalSection
+ GlobalSection(SolutionProperties) = preSolution
+ HideSolutionNode = FALSE
+ EndGlobalSection
+ GlobalSection(ExtensibilityGlobals) = postSolution
+ SolutionGuid = {EAA58685-56D9-43F2-8703-FD2CB020745E}
+ EndGlobalSection
+EndGlobal
diff --git a/src/deps/src/zlib/contrib/vstudio/vc17/zlibvc.vcxproj b/src/deps/src/zlib/contrib/vstudio/vc17/zlibvc.vcxproj
new file mode 100644
index 000000000..10a7a901e
--- /dev/null
+++ b/src/deps/src/zlib/contrib/vstudio/vc17/zlibvc.vcxproj
@@ -0,0 +1,875 @@
+
+
+
+
+ Debug
+ ARM
+
+
+ Debug
+ ARM64
+
+
+ Debug
+ Win32
+
+
+ Debug
+ x64
+
+
+ ReleaseWithoutAsm
+ ARM
+
+
+ ReleaseWithoutAsm
+ ARM64
+
+
+ ReleaseWithoutAsm
+ Win32
+
+
+ ReleaseWithoutAsm
+ x64
+
+
+ Release
+ ARM
+
+
+ Release
+ ARM64
+
+
+ Release
+ Win32
+
+
+ Release
+ x64
+
+
+
+ {8FD826F8-3739-44E6-8CC8-997122E53B8D}
+ 10.0
+
+
+
+ DynamicLibrary
+ false
+ true
+ v143
+
+
+ DynamicLibrary
+ false
+ true
+ v143
+
+
+ DynamicLibrary
+ false
+ v143
+ Unicode
+
+
+ DynamicLibrary
+ false
+ true
+ v143
+
+
+ DynamicLibrary
+ false
+ true
+ v143
+
+
+ DynamicLibrary
+ false
+ true
+ v143
+
+
+ DynamicLibrary
+ false
+ true
+ v143
+
+
+ DynamicLibrary
+ false
+ true
+ v143
+
+
+ DynamicLibrary
+ false
+ true
+ v143
+
+
+ DynamicLibrary
+ false
+ v143
+
+
+ DynamicLibrary
+ false
+ v143
+
+
+ DynamicLibrary
+ false
+ v143
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ <_ProjectFileVersion>10.0.30128.1
+ x86\ZlibDll$(Configuration)\
+ x86\ZlibDll$(Configuration)\Tmp\
+ true
+ false
+ x86\ZlibDll$(Configuration)\
+ x86\ZlibDll$(Configuration)\Tmp\
+ false
+ false
+ x86\ZlibDll$(Configuration)\
+ x86\ZlibDll$(Configuration)\Tmp\
+ false
+ false
+ x64\ZlibDll$(Configuration)\
+ x64\ZlibDll$(Configuration)\Tmp\
+ true
+ true
+ true
+ false
+ false
+ false
+ x64\ZlibDll$(Configuration)\
+ x64\ZlibDll$(Configuration)\Tmp\
+ false
+ false
+ false
+ false
+ false
+ false
+ x64\ZlibDll$(Configuration)\
+ x64\ZlibDll$(Configuration)\Tmp\
+ false
+ false
+ false
+ false
+ false
+ false
+ AllRules.ruleset
+
+
+ AllRules.ruleset
+ AllRules.ruleset
+ AllRules.ruleset
+
+
+
+
+
+
+ AllRules.ruleset
+
+
+ AllRules.ruleset
+ AllRules.ruleset
+ AllRules.ruleset
+
+
+
+
+
+
+ AllRules.ruleset
+
+
+ AllRules.ruleset
+ AllRules.ruleset
+ AllRules.ruleset
+
+
+
+
+
+
+ zlibwapi
+ zlibwapi
+ zlibwapi
+ zlibwapi
+ zlibwapi
+ zlibwapi
+ zlibwapi
+ zlibwapi
+ zlibwapi
+ zlibwapi
+ zlibwapi
+ zlibwapi
+
+
+ arm64\ZlibDll$(Configuration)\
+ arm64\ZlibDll$(Configuration)\Tmp\
+
+
+ arm\ZlibDll$(Configuration)\
+ arm\ZlibDll$(Configuration)\Tmp\
+
+
+ arm64\ZlibDll$(Configuration)\
+ arm64\ZlibDll$(Configuration)\Tmp\
+
+
+ arm64\ZlibDll$(Configuration)\
+ arm64\ZlibDll$(Configuration)\Tmp\
+
+
+ arm\ZlibDll$(Configuration)\
+ arm\ZlibDll$(Configuration)\Tmp\
+
+
+ arm\ZlibDll$(Configuration)\
+ arm\ZlibDll$(Configuration)\Tmp\
+
+
+
+ _DEBUG;%(PreprocessorDefinitions)
+ true
+ true
+ Win32
+ $(OutDir)zlibvc.tlb
+
+
+ Disabled
+ ..\..\..;%(AdditionalIncludeDirectories)
+ WIN32;_CRT_NONSTDC_NO_DEPRECATE;_CRT_SECURE_NO_DEPRECATE;_CRT_NONSTDC_NO_WARNINGS;ZLIB_WINAPI;%(PreprocessorDefinitions)
+
+
+ MultiThreadedDebugDLL
+ false
+ $(IntDir)zlibvc.pch
+ $(IntDir)
+ $(IntDir)
+ $(OutDir)
+
+
+ Level3
+ true
+ ProgramDatabase
+
+
+ _DEBUG;%(PreprocessorDefinitions)
+ 0x040c
+
+
+ /MACHINE:I386 %(AdditionalOptions)
+ %(AdditionalDependencies)
+ $(OutDir)zlibwapi.dll
+ true
+ .\zlibvc.def
+ true
+ $(OutDir)zlibwapi.pdb
+ true
+ $(OutDir)zlibwapi.map
+ Windows
+ false
+
+
+ $(OutDir)zlibwapi.lib
+
+
+
+
+ NDEBUG;%(PreprocessorDefinitions)
+ true
+ true
+ Win32
+ $(OutDir)zlibvc.tlb
+
+
+ OnlyExplicitInline
+ ..\..\..;%(AdditionalIncludeDirectories)
+ WIN32;_CRT_NONSTDC_NO_DEPRECATE;_CRT_SECURE_NO_DEPRECATE;_CRT_NONSTDC_NO_WARNINGS;ZLIB_WINAPI;%(PreprocessorDefinitions)
+ true
+
+
+ MultiThreadedDLL
+ false
+ true
+ $(IntDir)zlibvc.pch
+ All
+ $(IntDir)
+ $(IntDir)
+ $(OutDir)
+
+
+ Level3
+ true
+
+
+ NDEBUG;%(PreprocessorDefinitions)
+ 0x040c
+
+
+ /MACHINE:I386 %(AdditionalOptions)
+ $(OutDir)zlibwapi.dll
+ true
+ false
+ .\zlibvc.def
+ $(OutDir)zlibwapi.pdb
+ true
+ $(OutDir)zlibwapi.map
+ Windows
+ false
+
+
+ $(OutDir)zlibwapi.lib
+
+
+
+
+ NDEBUG;%(PreprocessorDefinitions)
+ true
+ true
+ Win32
+ $(OutDir)zlibvc.tlb
+
+
+ OnlyExplicitInline
+ ..\..\..;%(AdditionalIncludeDirectories)
+ WIN32;_CRT_NONSTDC_NO_DEPRECATE;_CRT_SECURE_NO_DEPRECATE;_CRT_NONSTDC_NO_WARNINGS;ZLIB_WINAPI;%(PreprocessorDefinitions)
+ true
+
+
+ MultiThreaded
+ false
+ true
+ $(IntDir)zlibvc.pch
+ All
+ $(IntDir)
+ $(IntDir)
+ $(OutDir)
+
+
+ Level3
+ true
+
+
+ NDEBUG;%(PreprocessorDefinitions)
+ 0x040c
+
+
+ /MACHINE:I386 %(AdditionalOptions)
+ %(AdditionalDependencies)
+ $(OutDir)zlibwapi.dll
+ true
+ false
+ .\zlibvc.def
+ $(OutDir)zlibwapi.pdb
+ true
+ $(OutDir)zlibwapi.map
+ Windows
+ false
+
+
+ $(OutDir)zlibwapi.lib
+ false
+
+
+
+
+ _DEBUG;%(PreprocessorDefinitions)
+ true
+ true
+ X64
+ $(OutDir)zlibvc.tlb
+
+
+ Disabled
+ ..\..\..;%(AdditionalIncludeDirectories)
+ WIN32;_CRT_NONSTDC_NO_DEPRECATE;_CRT_SECURE_NO_DEPRECATE;_CRT_NONSTDC_NO_WARNINGS;ZLIB_WINAPI;WIN64;%(PreprocessorDefinitions)
+
+
+ MultiThreadedDebugDLL
+ false
+ $(IntDir)zlibvc.pch
+ $(IntDir)
+ $(IntDir)
+ $(OutDir)
+
+
+ Level3
+ true
+ ProgramDatabase
+
+
+ _DEBUG;%(PreprocessorDefinitions)
+ 0x040c
+
+
+ %(AdditionalDependencies)
+ $(OutDir)zlibwapi.dll
+ true
+ .\zlibvc.def
+ true
+ $(OutDir)zlibwapi.pdb
+ true
+ $(OutDir)zlibwapi.map
+ Windows
+ $(OutDir)zlibwapi.lib
+ MachineX64
+
+
+
+
+ _DEBUG;%(PreprocessorDefinitions)
+ true
+ true
+ $(OutDir)zlibvc.tlb
+
+
+ Disabled
+ ..\..\..;%(AdditionalIncludeDirectories)
+ WIN32;_CRT_NONSTDC_NO_DEPRECATE;_CRT_SECURE_NO_DEPRECATE;_CRT_NONSTDC_NO_WARNINGS;ZLIB_WINAPI;WIN64;%(PreprocessorDefinitions)
+
+
+ MultiThreadedDebugDLL
+ false
+ $(IntDir)zlibvc.pch
+ $(IntDir)
+ $(IntDir)
+ $(OutDir)
+
+
+ Level3
+ true
+ ProgramDatabase
+
+
+ _DEBUG;%(PreprocessorDefinitions)
+ 0x040c
+
+
+ %(AdditionalDependencies)
+ $(OutDir)zlibwapi.dll
+ true
+ .\zlibvc.def
+ true
+ $(OutDir)zlibwapi.pdb
+ true
+ $(OutDir)zlibwapi.map
+ Windows
+ $(OutDir)zlibwapi.lib
+
+
+
+
+ _DEBUG;%(PreprocessorDefinitions)
+ true
+ true
+ $(OutDir)zlibvc.tlb
+
+
+ Disabled
+ ..\..\..;%(AdditionalIncludeDirectories)
+ WIN32;_CRT_NONSTDC_NO_DEPRECATE;_CRT_SECURE_NO_DEPRECATE;_CRT_NONSTDC_NO_WARNINGS;ZLIB_WINAPI;WIN64;%(PreprocessorDefinitions)
+
+
+ MultiThreadedDebugDLL
+ false
+ $(IntDir)zlibvc.pch
+ $(IntDir)
+ $(IntDir)
+ $(OutDir)
+
+
+ Level3
+ true
+ ProgramDatabase
+
+
+ _DEBUG;%(PreprocessorDefinitions)
+ 0x040c
+
+
+ %(AdditionalDependencies)
+ $(OutDir)zlibwapi.dll
+ true
+ .\zlibvc.def
+ true
+ $(OutDir)zlibwapi.pdb
+ true
+ $(OutDir)zlibwapi.map
+ Windows
+ $(OutDir)zlibwapi.lib
+
+
+
+
+ NDEBUG;%(PreprocessorDefinitions)
+ true
+ true
+ X64
+ $(OutDir)zlibvc.tlb
+
+
+ OnlyExplicitInline
+ ..\..\..;%(AdditionalIncludeDirectories)
+ WIN32;_CRT_NONSTDC_NO_DEPRECATE;_CRT_SECURE_NO_DEPRECATE;_CRT_NONSTDC_NO_WARNINGS;ZLIB_WINAPI;WIN64;%(PreprocessorDefinitions)
+ true
+
+
+ MultiThreadedDLL
+ false
+ true
+ $(IntDir)zlibvc.pch
+ All
+ $(IntDir)
+ $(IntDir)
+ $(OutDir)
+
+
+ Level3
+ true
+
+
+ NDEBUG;%(PreprocessorDefinitions)
+ 0x040c
+
+
+ $(OutDir)zlibwapi.dll
+ true
+ false
+ .\zlibvc.def
+ $(OutDir)zlibwapi.pdb
+ true
+ $(OutDir)zlibwapi.map
+ Windows
+ $(OutDir)zlibwapi.lib
+ MachineX64
+
+
+
+
+ NDEBUG;%(PreprocessorDefinitions)
+ true
+ true
+ $(OutDir)zlibvc.tlb
+
+
+ OnlyExplicitInline
+ ..\..\..;%(AdditionalIncludeDirectories)
+ WIN32;_CRT_NONSTDC_NO_DEPRECATE;_CRT_SECURE_NO_DEPRECATE;_CRT_NONSTDC_NO_WARNINGS;ZLIB_WINAPI;WIN64;%(PreprocessorDefinitions)
+ true
+
+
+ MultiThreadedDLL
+ false
+ true
+ $(IntDir)zlibvc.pch
+ All
+ $(IntDir)
+ $(IntDir)
+ $(OutDir)
+
+
+ Level3
+ true
+
+
+ NDEBUG;%(PreprocessorDefinitions)
+ 0x040c
+
+
+ $(OutDir)zlibwapi.dll
+ true
+ false
+ .\zlibvc.def
+ $(OutDir)zlibwapi.pdb
+ true
+ $(OutDir)zlibwapi.map
+ Windows
+ $(OutDir)zlibwapi.lib
+
+
+
+
+ NDEBUG;%(PreprocessorDefinitions)
+ true
+ true
+ $(OutDir)zlibvc.tlb
+
+
+ OnlyExplicitInline
+ ..\..\..;%(AdditionalIncludeDirectories)
+ WIN32;_CRT_NONSTDC_NO_DEPRECATE;_CRT_SECURE_NO_DEPRECATE;_CRT_NONSTDC_NO_WARNINGS;ZLIB_WINAPI;WIN64;%(PreprocessorDefinitions)
+ true
+
+
+ MultiThreadedDLL
+ false
+ true
+ $(IntDir)zlibvc.pch
+ All
+ $(IntDir)
+ $(IntDir)
+ $(OutDir)
+
+
+ Level3
+ true
+
+
+ NDEBUG;%(PreprocessorDefinitions)
+ 0x040c
+
+
+ $(OutDir)zlibwapi.dll
+ true
+ false
+ .\zlibvc.def
+ $(OutDir)zlibwapi.pdb
+ true
+ $(OutDir)zlibwapi.map
+ Windows
+ $(OutDir)zlibwapi.lib
+
+
+
+
+ NDEBUG;%(PreprocessorDefinitions)
+ true
+ true
+ X64
+ $(OutDir)zlibvc.tlb
+
+
+ OnlyExplicitInline
+ ..\..\..;%(AdditionalIncludeDirectories)
+ _CRT_NONSTDC_NO_DEPRECATE;_CRT_SECURE_NO_DEPRECATE;_CRT_NONSTDC_NO_WARNINGS;ZLIB_WINAPI;WIN64;%(PreprocessorDefinitions)
+ true
+
+
+ MultiThreadedDLL
+ false
+ true
+ $(IntDir)zlibvc.pch
+ All
+ $(IntDir)
+ $(IntDir)
+ $(OutDir)
+
+
+ Level3
+ true
+
+
+ NDEBUG;%(PreprocessorDefinitions)
+ 0x040c
+
+
+ %(AdditionalDependencies)
+ $(OutDir)zlibwapi.dll
+ true
+ false
+ .\zlibvc.def
+ $(OutDir)zlibwapi.pdb
+ true
+ $(OutDir)zlibwapi.map
+ Windows
+ $(OutDir)zlibwapi.lib
+ MachineX64
+
+
+
+
+ NDEBUG;%(PreprocessorDefinitions)
+ true
+ true
+ $(OutDir)zlibvc.tlb
+
+
+ OnlyExplicitInline
+ ..\..\..;%(AdditionalIncludeDirectories)
+ _CRT_NONSTDC_NO_DEPRECATE;_CRT_SECURE_NO_DEPRECATE;_CRT_NONSTDC_NO_WARNINGS;ZLIB_WINAPI;WIN64;%(PreprocessorDefinitions)
+ true
+
+
+ MultiThreadedDLL
+ false
+ true
+ $(IntDir)zlibvc.pch
+ All
+ $(IntDir)
+ $(IntDir)
+ $(OutDir)
+
+
+ Level3
+ true
+
+
+ NDEBUG;%(PreprocessorDefinitions)
+ 0x040c
+
+
+ %(AdditionalDependencies)
+ $(OutDir)zlibwapi.dll
+ true
+ false
+ .\zlibvc.def
+ $(OutDir)zlibwapi.pdb
+ true
+ $(OutDir)zlibwapi.map
+ Windows
+ $(OutDir)zlibwapi.lib
+
+
+
+
+ NDEBUG;%(PreprocessorDefinitions)
+ true
+ true
+ $(OutDir)zlibvc.tlb
+
+
+ OnlyExplicitInline
+ ..\..\..;%(AdditionalIncludeDirectories)
+ _CRT_NONSTDC_NO_DEPRECATE;_CRT_SECURE_NO_DEPRECATE;_CRT_NONSTDC_NO_WARNINGS;ZLIB_WINAPI;WIN32;%(PreprocessorDefinitions)
+ true
+
+
+ MultiThreadedDLL
+ false
+ true
+ $(IntDir)zlibvc.pch
+ All
+ $(IntDir)
+ $(IntDir)
+ $(OutDir)
+
+
+ Level3
+ true
+
+
+ NDEBUG;%(PreprocessorDefinitions)
+ 0x040c
+
+
+ %(AdditionalDependencies)
+ $(OutDir)zlibwapi.dll
+ true
+ false
+ .\zlibvc.def
+ $(OutDir)zlibwapi.pdb
+ true
+ $(OutDir)zlibwapi.map
+ Windows
+ $(OutDir)zlibwapi.lib
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ %(AdditionalIncludeDirectories)
+ ZLIB_INTERNAL;%(PreprocessorDefinitions)
+ %(AdditionalIncludeDirectories)
+ %(AdditionalIncludeDirectories)
+ %(AdditionalIncludeDirectories)
+ ZLIB_INTERNAL;%(PreprocessorDefinitions)
+ ZLIB_INTERNAL;%(PreprocessorDefinitions)
+ ZLIB_INTERNAL;%(PreprocessorDefinitions)
+
+
+ %(AdditionalIncludeDirectories)
+ ZLIB_INTERNAL;%(PreprocessorDefinitions)
+ %(AdditionalIncludeDirectories)
+ %(AdditionalIncludeDirectories)
+ %(AdditionalIncludeDirectories)
+ ZLIB_INTERNAL;%(PreprocessorDefinitions)
+ ZLIB_INTERNAL;%(PreprocessorDefinitions)
+ ZLIB_INTERNAL;%(PreprocessorDefinitions)
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/src/deps/src/zlib/contrib/vstudio/vc9/zlib.rc b/src/deps/src/zlib/contrib/vstudio/vc9/zlib.rc
index 29af8e11a..856bd11f0 100644
--- a/src/deps/src/zlib/contrib/vstudio/vc9/zlib.rc
+++ b/src/deps/src/zlib/contrib/vstudio/vc9/zlib.rc
@@ -2,8 +2,8 @@
#define IDR_VERSION1 1
IDR_VERSION1 VERSIONINFO MOVEABLE IMPURE LOADONCALL DISCARDABLE
- FILEVERSION 1, 3, 0, 0
- PRODUCTVERSION 1, 3, 0, 0
+ FILEVERSION 1, 3, 1, 0
+ PRODUCTVERSION 1, 3, 1, 0
FILEFLAGSMASK VS_FFI_FILEFLAGSMASK
FILEFLAGS 0
FILEOS VOS_DOS_WINDOWS32
@@ -17,12 +17,12 @@ BEGIN
BEGIN
VALUE "FileDescription", "zlib data compression and ZIP file I/O library\0"
- VALUE "FileVersion", "1.3.0\0"
+ VALUE "FileVersion", "1.3.1\0"
VALUE "InternalName", "zlib\0"
VALUE "OriginalFilename", "zlibwapi.dll\0"
VALUE "ProductName", "ZLib.DLL\0"
VALUE "Comments","DLL support by Alessandro Iacopetti & Gilles Vollant\0"
- VALUE "LegalCopyright", "(C) 1995-2023 Jean-loup Gailly & Mark Adler\0"
+ VALUE "LegalCopyright", "(C) 1995-2024 Jean-loup Gailly & Mark Adler\0"
END
END
BLOCK "VarFileInfo"
diff --git a/src/deps/src/zlib/contrib/vstudio/vc9/zlibvc.def b/src/deps/src/zlib/contrib/vstudio/vc9/zlibvc.def
index f28aa6c73..3234a02d9 100644
--- a/src/deps/src/zlib/contrib/vstudio/vc9/zlibvc.def
+++ b/src/deps/src/zlib/contrib/vstudio/vc9/zlibvc.def
@@ -1,7 +1,7 @@
LIBRARY
; zlib data compression and ZIP file I/O library
-VERSION 1.3
+VERSION 1.3.1
EXPORTS
adler32 @1
diff --git a/src/deps/src/zlib/deflate.c b/src/deps/src/zlib/deflate.c
index bd0117519..012ea8148 100644
--- a/src/deps/src/zlib/deflate.c
+++ b/src/deps/src/zlib/deflate.c
@@ -1,5 +1,5 @@
/* deflate.c -- compress data using the deflation algorithm
- * Copyright (C) 1995-2023 Jean-loup Gailly and Mark Adler
+ * Copyright (C) 1995-2024 Jean-loup Gailly and Mark Adler
* For conditions of distribution and use, see copyright notice in zlib.h
*/
@@ -52,7 +52,7 @@
#include "deflate.h"
const char deflate_copyright[] =
- " deflate 1.3 Copyright 1995-2023 Jean-loup Gailly and Mark Adler ";
+ " deflate 1.3.1 Copyright 1995-2024 Jean-loup Gailly and Mark Adler ";
/*
If you use the zlib library in a product, an acknowledgment is welcome
in the documentation of your product. If for some reason you cannot
@@ -493,7 +493,7 @@ int ZEXPORT deflateInit2_(z_streamp strm, int level, int method,
* symbols from which it is being constructed.
*/
- s->pending_buf = (uchf *) ZALLOC(strm, s->lit_bufsize, 4);
+ s->pending_buf = (uchf *) ZALLOC(strm, s->lit_bufsize, LIT_BUFS);
s->pending_buf_size = (ulg)s->lit_bufsize * 4;
if (s->window == Z_NULL || s->prev == Z_NULL || s->head == Z_NULL ||
@@ -503,8 +503,14 @@ int ZEXPORT deflateInit2_(z_streamp strm, int level, int method,
deflateEnd (strm);
return Z_MEM_ERROR;
}
+#ifdef LIT_MEM
+ s->d_buf = (ushf *)(s->pending_buf + (s->lit_bufsize << 1));
+ s->l_buf = s->pending_buf + (s->lit_bufsize << 2);
+ s->sym_end = s->lit_bufsize - 1;
+#else
s->sym_buf = s->pending_buf + s->lit_bufsize;
s->sym_end = (s->lit_bufsize - 1) * 3;
+#endif
/* We avoid equality with lit_bufsize*3 because of wraparound at 64K
* on 16 bit machines and because stored blocks are restricted to
* 64K-1 bytes.
@@ -720,9 +726,15 @@ int ZEXPORT deflatePrime(z_streamp strm, int bits, int value) {
if (deflateStateCheck(strm)) return Z_STREAM_ERROR;
s = strm->state;
+#ifdef LIT_MEM
+ if (bits < 0 || bits > 16 ||
+ (uchf *)s->d_buf < s->pending_out + ((Buf_size + 7) >> 3))
+ return Z_BUF_ERROR;
+#else
if (bits < 0 || bits > 16 ||
s->sym_buf < s->pending_out + ((Buf_size + 7) >> 3))
return Z_BUF_ERROR;
+#endif
do {
put = Buf_size - s->bi_valid;
if (put > bits)
@@ -1294,7 +1306,7 @@ int ZEXPORT deflateCopy(z_streamp dest, z_streamp source) {
ds->window = (Bytef *) ZALLOC(dest, ds->w_size, 2*sizeof(Byte));
ds->prev = (Posf *) ZALLOC(dest, ds->w_size, sizeof(Pos));
ds->head = (Posf *) ZALLOC(dest, ds->hash_size, sizeof(Pos));
- ds->pending_buf = (uchf *) ZALLOC(dest, ds->lit_bufsize, 4);
+ ds->pending_buf = (uchf *) ZALLOC(dest, ds->lit_bufsize, LIT_BUFS);
if (ds->window == Z_NULL || ds->prev == Z_NULL || ds->head == Z_NULL ||
ds->pending_buf == Z_NULL) {
@@ -1305,10 +1317,15 @@ int ZEXPORT deflateCopy(z_streamp dest, z_streamp source) {
zmemcpy(ds->window, ss->window, ds->w_size * 2 * sizeof(Byte));
zmemcpy((voidpf)ds->prev, (voidpf)ss->prev, ds->w_size * sizeof(Pos));
zmemcpy((voidpf)ds->head, (voidpf)ss->head, ds->hash_size * sizeof(Pos));
- zmemcpy(ds->pending_buf, ss->pending_buf, (uInt)ds->pending_buf_size);
+ zmemcpy(ds->pending_buf, ss->pending_buf, ds->lit_bufsize * LIT_BUFS);
ds->pending_out = ds->pending_buf + (ss->pending_out - ss->pending_buf);
+#ifdef LIT_MEM
+ ds->d_buf = (ushf *)(ds->pending_buf + (ds->lit_bufsize << 1));
+ ds->l_buf = ds->pending_buf + (ds->lit_bufsize << 2);
+#else
ds->sym_buf = ds->pending_buf + ds->lit_bufsize;
+#endif
ds->l_desc.dyn_tree = ds->dyn_ltree;
ds->d_desc.dyn_tree = ds->dyn_dtree;
@@ -1539,13 +1556,21 @@ local uInt longest_match(deflate_state *s, IPos cur_match) {
*/
local void check_match(deflate_state *s, IPos start, IPos match, int length) {
/* check that the match is indeed a match */
- if (zmemcmp(s->window + match,
- s->window + start, length) != EQUAL) {
- fprintf(stderr, " start %u, match %u, length %d\n",
- start, match, length);
+ Bytef *back = s->window + (int)match, *here = s->window + start;
+ IPos len = length;
+ if (match == (IPos)-1) {
+ /* match starts one byte before the current window -- just compare the
+ subsequent length-1 bytes */
+ back++;
+ here++;
+ len--;
+ }
+ if (zmemcmp(back, here, len) != EQUAL) {
+ fprintf(stderr, " start %u, match %d, length %d\n",
+ start, (int)match, length);
do {
- fprintf(stderr, "%c%c", s->window[match++], s->window[start++]);
- } while (--length != 0);
+ fprintf(stderr, "(%02x %02x)", *back++, *here++);
+ } while (--len != 0);
z_error("invalid match");
}
if (z_verbose > 1) {
diff --git a/src/deps/src/zlib/deflate.h b/src/deps/src/zlib/deflate.h
index 869679142..300c6ada6 100644
--- a/src/deps/src/zlib/deflate.h
+++ b/src/deps/src/zlib/deflate.h
@@ -1,5 +1,5 @@
/* deflate.h -- internal compression state
- * Copyright (C) 1995-2018 Jean-loup Gailly
+ * Copyright (C) 1995-2024 Jean-loup Gailly
* For conditions of distribution and use, see copyright notice in zlib.h
*/
@@ -23,6 +23,10 @@
# define GZIP
#endif
+/* define LIT_MEM to slightly increase the speed of deflate (order 1% to 2%) at
+ the cost of a larger memory footprint */
+/* #define LIT_MEM */
+
/* ===========================================================================
* Internal compression state.
*/
@@ -217,7 +221,14 @@ typedef struct internal_state {
/* Depth of each subtree used as tie breaker for trees of equal frequency
*/
+#ifdef LIT_MEM
+# define LIT_BUFS 5
+ ushf *d_buf; /* buffer for distances */
+ uchf *l_buf; /* buffer for literals/lengths */
+#else
+# define LIT_BUFS 4
uchf *sym_buf; /* buffer for distances and literals/lengths */
+#endif
uInt lit_bufsize;
/* Size of match buffer for literals/lengths. There are 4 reasons for
@@ -239,7 +250,7 @@ typedef struct internal_state {
* - I can't count above 4
*/
- uInt sym_next; /* running index in sym_buf */
+ uInt sym_next; /* running index in symbol buffer */
uInt sym_end; /* symbol table full when sym_next reaches this */
ulg opt_len; /* bit length of current block with optimal trees */
@@ -318,6 +329,25 @@ void ZLIB_INTERNAL _tr_stored_block(deflate_state *s, charf *buf,
extern const uch ZLIB_INTERNAL _dist_code[];
#endif
+#ifdef LIT_MEM
+# define _tr_tally_lit(s, c, flush) \
+ { uch cc = (c); \
+ s->d_buf[s->sym_next] = 0; \
+ s->l_buf[s->sym_next++] = cc; \
+ s->dyn_ltree[cc].Freq++; \
+ flush = (s->sym_next == s->sym_end); \
+ }
+# define _tr_tally_dist(s, distance, length, flush) \
+ { uch len = (uch)(length); \
+ ush dist = (ush)(distance); \
+ s->d_buf[s->sym_next] = dist; \
+ s->l_buf[s->sym_next++] = len; \
+ dist--; \
+ s->dyn_ltree[_length_code[len]+LITERALS+1].Freq++; \
+ s->dyn_dtree[d_code(dist)].Freq++; \
+ flush = (s->sym_next == s->sym_end); \
+ }
+#else
# define _tr_tally_lit(s, c, flush) \
{ uch cc = (c); \
s->sym_buf[s->sym_next++] = 0; \
@@ -337,6 +367,7 @@ void ZLIB_INTERNAL _tr_stored_block(deflate_state *s, charf *buf,
s->dyn_dtree[d_code(dist)].Freq++; \
flush = (s->sym_next == s->sym_end); \
}
+#endif
#else
# define _tr_tally_lit(s, c, flush) flush = _tr_tally(s, 0, c)
# define _tr_tally_dist(s, distance, length, flush) \
diff --git a/src/deps/src/zlib/doc/algorithm.txt b/src/deps/src/zlib/doc/algorithm.txt
index c97f49502..029e5a313 100644
--- a/src/deps/src/zlib/doc/algorithm.txt
+++ b/src/deps/src/zlib/doc/algorithm.txt
@@ -77,7 +77,7 @@ table took no time (and if you had infinite memory), then there would only
be a first level table to cover all the way to the longest code. However,
building the table ends up taking a lot longer for more bits since short
codes are replicated many times in such a table. What inflate() does is
-simply to make the number of bits in the first table a variable, and then
+simply to make the number of bits in the first table a variable, and then
to set that variable for the maximum speed.
For inflate, which has 286 possible codes for the literal/length tree, the size
diff --git a/src/deps/src/zlib/examples/gzlog.c b/src/deps/src/zlib/examples/gzlog.c
index b977802dd..da1b02e73 100644
--- a/src/deps/src/zlib/examples/gzlog.c
+++ b/src/deps/src/zlib/examples/gzlog.c
@@ -212,8 +212,8 @@
to the appropriate recovery below. If there is no foo.add file, provide
a zero data length to the recovery. In that case, the append recovery
restores the foo.gz to the previous compressed + uncompressed data state.
- For the the compress recovery, a missing foo.add file results in foo.gz
- being restored to the previous compressed-only data state.
+ For the compress recovery, a missing foo.add file results in foo.gz being
+ restored to the previous compressed-only data state.
- Append recovery:
- Pick up append at + step above
- Compress recovery:
diff --git a/src/deps/src/zlib/examples/zran.c b/src/deps/src/zlib/examples/zran.c
index 32c93686c..d3135955b 100644
--- a/src/deps/src/zlib/examples/zran.c
+++ b/src/deps/src/zlib/examples/zran.c
@@ -267,7 +267,7 @@ static inline void append_bits(unsigned value, int bits,
}
}
-// Insert enough bits in the form of empty deflate blocks in front of the the
+// Insert enough bits in the form of empty deflate blocks in front of the
// low bits bits of value, in order to bring the sequence to a byte boundary.
// Then feed that to inflate(). This does what inflatePrime() does, except that
// a negative value of bits is not supported. bits must be in 0..16. If the
diff --git a/src/deps/src/zlib/gzguts.h b/src/deps/src/zlib/gzguts.h
index f9375047e..eba72085b 100644
--- a/src/deps/src/zlib/gzguts.h
+++ b/src/deps/src/zlib/gzguts.h
@@ -1,5 +1,5 @@
/* gzguts.h -- zlib internal header definitions for gz* operations
- * Copyright (C) 2004-2019 Mark Adler
+ * Copyright (C) 2004-2024 Mark Adler
* For conditions of distribution and use, see copyright notice in zlib.h
*/
@@ -210,9 +210,5 @@ char ZLIB_INTERNAL *gz_strwinerror(DWORD error);
/* GT_OFF(x), where x is an unsigned value, is true if x > maximum z_off64_t
value -- needed when comparing unsigned to z_off64_t, which is signed
(possible z_off64_t types off_t, off64_t, and long are all signed) */
-#ifdef INT_MAX
-# define GT_OFF(x) (sizeof(int) == sizeof(z_off64_t) && (x) > INT_MAX)
-#else
unsigned ZLIB_INTERNAL gz_intmax(void);
-# define GT_OFF(x) (sizeof(int) == sizeof(z_off64_t) && (x) > gz_intmax())
-#endif
+#define GT_OFF(x) (sizeof(int) == sizeof(z_off64_t) && (x) > gz_intmax())
diff --git a/src/deps/src/zlib/gzlib.c b/src/deps/src/zlib/gzlib.c
index 29fc4486f..983153cc8 100644
--- a/src/deps/src/zlib/gzlib.c
+++ b/src/deps/src/zlib/gzlib.c
@@ -1,5 +1,5 @@
/* gzlib.c -- zlib functions common to reading and writing gzip files
- * Copyright (C) 2004-2019 Mark Adler
+ * Copyright (C) 2004-2024 Mark Adler
* For conditions of distribution and use, see copyright notice in zlib.h
*/
@@ -563,20 +563,20 @@ void ZLIB_INTERNAL gz_error(gz_statep state, int err, const char *msg) {
#endif
}
-#ifndef INT_MAX
/* portably return maximum value for an int (when limits.h presumed not
available) -- we need to do this to cover cases where 2's complement not
used, since C standard permits 1's complement and sign-bit representations,
otherwise we could just use ((unsigned)-1) >> 1 */
unsigned ZLIB_INTERNAL gz_intmax(void) {
- unsigned p, q;
-
- p = 1;
+#ifdef INT_MAX
+ return INT_MAX;
+#else
+ unsigned p = 1, q;
do {
q = p;
p <<= 1;
p++;
} while (p > q);
return q >> 1;
-}
#endif
+}
diff --git a/src/deps/src/zlib/inflate.c b/src/deps/src/zlib/inflate.c
index b0757a9b2..94ecff015 100644
--- a/src/deps/src/zlib/inflate.c
+++ b/src/deps/src/zlib/inflate.c
@@ -1387,7 +1387,7 @@ int ZEXPORT inflateSync(z_streamp strm) {
/* if first time, start search in bit buffer */
if (state->mode != SYNC) {
state->mode = SYNC;
- state->hold <<= state->bits & 7;
+ state->hold >>= state->bits & 7;
state->bits -= state->bits & 7;
len = 0;
while (state->bits >= 8) {
diff --git a/src/deps/src/zlib/inftrees.c b/src/deps/src/zlib/inftrees.c
index 8a208c2da..98cfe1644 100644
--- a/src/deps/src/zlib/inftrees.c
+++ b/src/deps/src/zlib/inftrees.c
@@ -1,5 +1,5 @@
/* inftrees.c -- generate Huffman trees for efficient decoding
- * Copyright (C) 1995-2023 Mark Adler
+ * Copyright (C) 1995-2024 Mark Adler
* For conditions of distribution and use, see copyright notice in zlib.h
*/
@@ -9,7 +9,7 @@
#define MAXBITS 15
const char inflate_copyright[] =
- " inflate 1.3 Copyright 1995-2023 Mark Adler ";
+ " inflate 1.3.1 Copyright 1995-2024 Mark Adler ";
/*
If you use the zlib library in a product, an acknowledgment is welcome
in the documentation of your product. If for some reason you cannot
@@ -57,7 +57,7 @@ int ZLIB_INTERNAL inflate_table(codetype type, unsigned short FAR *lens,
35, 43, 51, 59, 67, 83, 99, 115, 131, 163, 195, 227, 258, 0, 0};
static const unsigned short lext[31] = { /* Length codes 257..285 extra */
16, 16, 16, 16, 16, 16, 16, 16, 17, 17, 17, 17, 18, 18, 18, 18,
- 19, 19, 19, 19, 20, 20, 20, 20, 21, 21, 21, 21, 16, 198, 203};
+ 19, 19, 19, 19, 20, 20, 20, 20, 21, 21, 21, 21, 16, 203, 77};
static const unsigned short dbase[32] = { /* Distance codes 0..29 base */
1, 2, 3, 4, 5, 7, 9, 13, 17, 25, 33, 49, 65, 97, 129, 193,
257, 385, 513, 769, 1025, 1537, 2049, 3073, 4097, 6145,
diff --git a/src/deps/src/zlib/inftrees.h b/src/deps/src/zlib/inftrees.h
index a10712d8c..396f74b5d 100644
--- a/src/deps/src/zlib/inftrees.h
+++ b/src/deps/src/zlib/inftrees.h
@@ -41,8 +41,8 @@ typedef struct {
examples/enough.c found in the zlib distribution. The arguments to that
program are the number of symbols, the initial root table size, and the
maximum bit length of a code. "enough 286 9 15" for literal/length codes
- returns returns 852, and "enough 30 6 15" for distance codes returns 592.
- The initial root table size (9 or 6) is found in the fifth argument of the
+ returns 852, and "enough 30 6 15" for distance codes returns 592. The
+ initial root table size (9 or 6) is found in the fifth argument of the
inflate_table() calls in inflate.c and infback.c. If the root table size is
changed, then these maximum sizes would be need to be recalculated and
updated. */
diff --git a/src/deps/src/zlib/old/visual-basic.txt b/src/deps/src/zlib/old/visual-basic.txt
index 57efe5812..3c8d2a42d 100644
--- a/src/deps/src/zlib/old/visual-basic.txt
+++ b/src/deps/src/zlib/old/visual-basic.txt
@@ -115,7 +115,7 @@ SUCCESS Then
ReDim Preserve bytaryCpr(lngCprSiz - 1)
Open strCprPth For Binary Access Write As #1
Put #1, , bytaryCpr()
- Put #1, , lngOriSiz 'Add the the original size value to the end
+ Put #1, , lngOriSiz 'Add the original size value to the end
(last 4 bytes)
Close #1
Else
diff --git a/src/deps/src/zlib/os400/README400 b/src/deps/src/zlib/os400/README400
index 6dd41aa65..30ed5a12c 100644
--- a/src/deps/src/zlib/os400/README400
+++ b/src/deps/src/zlib/os400/README400
@@ -1,4 +1,4 @@
- ZLIB version 1.3.0 for OS/400 installation instructions
+ ZLIB version 1.3.1 for OS/400 installation instructions
1) Download and unpack the zlib tarball to some IFS directory.
(i.e.: /path/to/the/zlib/ifs/source/directory)
diff --git a/src/deps/src/zlib/os400/zlib.inc b/src/deps/src/zlib/os400/zlib.inc
index 0d9e2f209..744729ab9 100644
--- a/src/deps/src/zlib/os400/zlib.inc
+++ b/src/deps/src/zlib/os400/zlib.inc
@@ -1,7 +1,7 @@
* ZLIB.INC - Interface to the general purpose compression library
*
* ILE RPG400 version by Patrick Monnerat, DATASPHERE.
- * Version 1.3.0
+ * Version 1.3.1
*
*
* WARNING:
@@ -22,12 +22,12 @@
*
* Versioning information.
*
- D ZLIB_VERSION C '1.3.0'
+ D ZLIB_VERSION C '1.3.1'
D ZLIB_VERNUM C X'12a0'
D ZLIB_VER_MAJOR C 1
D ZLIB_VER_MINOR C 3
D ZLIB_VER_REVISION...
- D C 0
+ D C 1
D ZLIB_VER_SUBREVISION...
D C 0
*
diff --git a/src/deps/src/zlib/qnx/package.qpg b/src/deps/src/zlib/qnx/package.qpg
index d882af2bf..4877e0ef0 100644
--- a/src/deps/src/zlib/qnx/package.qpg
+++ b/src/deps/src/zlib/qnx/package.qpg
@@ -25,10 +25,10 @@
-
-
-
-
+
+
+
+
@@ -63,7 +63,7 @@
- 1.3.0
+ 1.3.1
Medium
Stable
diff --git a/src/deps/src/zlib/test/example.c b/src/deps/src/zlib/test/example.c
index 582a17a3c..c3521dd59 100644
--- a/src/deps/src/zlib/test/example.c
+++ b/src/deps/src/zlib/test/example.c
@@ -36,12 +36,12 @@ static uLong dictId; /* Adler32 value of the dictionary */
#ifdef Z_SOLO
-void *myalloc(void *q, unsigned n, unsigned m) {
+static void *myalloc(void *q, unsigned n, unsigned m) {
(void)q;
return calloc(n, m);
}
-void myfree(void *q, void *p) {
+static void myfree(void *q, void *p) {
(void)q;
free(p);
}
@@ -57,7 +57,7 @@ static free_func zfree = (free_func)0;
/* ===========================================================================
* Test compress() and uncompress()
*/
-void test_compress(Byte *compr, uLong comprLen, Byte *uncompr,
+static void test_compress(Byte *compr, uLong comprLen, Byte *uncompr,
uLong uncomprLen) {
int err;
uLong len = (uLong)strlen(hello)+1;
@@ -81,7 +81,7 @@ void test_compress(Byte *compr, uLong comprLen, Byte *uncompr,
/* ===========================================================================
* Test read/write of .gz files
*/
-void test_gzio(const char *fname, Byte *uncompr, uLong uncomprLen) {
+static void test_gzio(const char *fname, Byte *uncompr, uLong uncomprLen) {
#ifdef NO_GZCOMPRESS
fprintf(stderr, "NO_GZCOMPRESS -- gz* functions cannot compress\n");
#else
@@ -163,7 +163,7 @@ void test_gzio(const char *fname, Byte *uncompr, uLong uncomprLen) {
/* ===========================================================================
* Test deflate() with small buffers
*/
-void test_deflate(Byte *compr, uLong comprLen) {
+static void test_deflate(Byte *compr, uLong comprLen) {
z_stream c_stream; /* compression stream */
int err;
uLong len = (uLong)strlen(hello)+1;
@@ -198,7 +198,7 @@ void test_deflate(Byte *compr, uLong comprLen) {
/* ===========================================================================
* Test inflate() with small buffers
*/
-void test_inflate(Byte *compr, uLong comprLen, Byte *uncompr,
+static void test_inflate(Byte *compr, uLong comprLen, Byte *uncompr,
uLong uncomprLen) {
int err;
z_stream d_stream; /* decompression stream */
@@ -237,7 +237,7 @@ void test_inflate(Byte *compr, uLong comprLen, Byte *uncompr,
/* ===========================================================================
* Test deflate() with large buffers and dynamic change of compression level
*/
-void test_large_deflate(Byte *compr, uLong comprLen, Byte *uncompr,
+static void test_large_deflate(Byte *compr, uLong comprLen, Byte *uncompr,
uLong uncomprLen) {
z_stream c_stream; /* compression stream */
int err;
@@ -290,7 +290,7 @@ void test_large_deflate(Byte *compr, uLong comprLen, Byte *uncompr,
/* ===========================================================================
* Test inflate() with large buffers
*/
-void test_large_inflate(Byte *compr, uLong comprLen, Byte *uncompr,
+static void test_large_inflate(Byte *compr, uLong comprLen, Byte *uncompr,
uLong uncomprLen) {
int err;
z_stream d_stream; /* decompression stream */
@@ -329,7 +329,7 @@ void test_large_inflate(Byte *compr, uLong comprLen, Byte *uncompr,
/* ===========================================================================
* Test deflate() with full flush
*/
-void test_flush(Byte *compr, uLong *comprLen) {
+static void test_flush(Byte *compr, uLong *comprLen) {
z_stream c_stream; /* compression stream */
int err;
uInt len = (uInt)strlen(hello)+1;
@@ -364,7 +364,8 @@ void test_flush(Byte *compr, uLong *comprLen) {
/* ===========================================================================
* Test inflateSync()
*/
-void test_sync(Byte *compr, uLong comprLen, Byte *uncompr, uLong uncomprLen) {
+static void test_sync(Byte *compr, uLong comprLen, Byte *uncompr,
+ uLong uncomprLen) {
int err;
z_stream d_stream; /* decompression stream */
@@ -404,7 +405,7 @@ void test_sync(Byte *compr, uLong comprLen, Byte *uncompr, uLong uncomprLen) {
/* ===========================================================================
* Test deflate() with preset dictionary
*/
-void test_dict_deflate(Byte *compr, uLong comprLen) {
+static void test_dict_deflate(Byte *compr, uLong comprLen) {
z_stream c_stream; /* compression stream */
int err;
@@ -438,7 +439,7 @@ void test_dict_deflate(Byte *compr, uLong comprLen) {
/* ===========================================================================
* Test inflate() with a preset dictionary
*/
-void test_dict_inflate(Byte *compr, uLong comprLen, Byte *uncompr,
+static void test_dict_inflate(Byte *compr, uLong comprLen, Byte *uncompr,
uLong uncomprLen) {
int err;
z_stream d_stream; /* decompression stream */
diff --git a/src/deps/src/zlib/test/minigzip.c b/src/deps/src/zlib/test/minigzip.c
index 8a21ddfb5..134e10e6c 100644
--- a/src/deps/src/zlib/test/minigzip.c
+++ b/src/deps/src/zlib/test/minigzip.c
@@ -149,12 +149,12 @@ static void pwinerror (s)
# include /* for unlink() */
#endif
-void *myalloc(void *q, unsigned n, unsigned m) {
+static void *myalloc(void *q, unsigned n, unsigned m) {
(void)q;
return calloc(n, m);
}
-void myfree(void *q, void *p) {
+static void myfree(void *q, void *p) {
(void)q;
free(p);
}
@@ -167,7 +167,7 @@ typedef struct gzFile_s {
z_stream strm;
} *gzFile;
-gzFile gz_open(const char *path, int fd, const char *mode) {
+static gzFile gz_open(const char *path, int fd, const char *mode) {
gzFile gz;
int ret;
@@ -201,15 +201,15 @@ gzFile gz_open(const char *path, int fd, const char *mode) {
return gz;
}
-gzFile gzopen(const char *path, const char *mode) {
+static gzFile gzopen(const char *path, const char *mode) {
return gz_open(path, -1, mode);
}
-gzFile gzdopen(int fd, const char *mode) {
+static gzFile gzdopen(int fd, const char *mode) {
return gz_open(NULL, fd, mode);
}
-int gzwrite(gzFile gz, const void *buf, unsigned len) {
+static int gzwrite(gzFile gz, const void *buf, unsigned len) {
z_stream *strm;
unsigned char out[BUFLEN];
@@ -227,7 +227,7 @@ int gzwrite(gzFile gz, const void *buf, unsigned len) {
return len;
}
-int gzread(gzFile gz, void *buf, unsigned len) {
+static int gzread(gzFile gz, void *buf, unsigned len) {
int ret;
unsigned got;
unsigned char in[1];
@@ -258,7 +258,7 @@ int gzread(gzFile gz, void *buf, unsigned len) {
return len - strm->avail_out;
}
-int gzclose(gzFile gz) {
+static int gzclose(gzFile gz) {
z_stream *strm;
unsigned char out[BUFLEN];
@@ -283,7 +283,7 @@ int gzclose(gzFile gz) {
return Z_OK;
}
-const char *gzerror(gzFile gz, int *err) {
+static const char *gzerror(gzFile gz, int *err) {
*err = gz->err;
return gz->msg;
}
@@ -295,7 +295,7 @@ static char *prog;
/* ===========================================================================
* Display error message and exit
*/
-void error(const char *msg) {
+static void error(const char *msg) {
fprintf(stderr, "%s: %s\n", prog, msg);
exit(1);
}
@@ -303,9 +303,9 @@ void error(const char *msg) {
#ifdef USE_MMAP /* MMAP version, Miguel Albrecht */
/* Try compressing the input file at once using mmap. Return Z_OK if
- * if success, Z_ERRNO otherwise.
+ * success, Z_ERRNO otherwise.
*/
-int gz_compress_mmap(FILE *in, gzFile out) {
+static int gz_compress_mmap(FILE *in, gzFile out) {
int len;
int err;
int ifd = fileno(in);
@@ -338,7 +338,7 @@ int gz_compress_mmap(FILE *in, gzFile out) {
* Compress input to output then close both files.
*/
-void gz_compress(FILE *in, gzFile out) {
+static void gz_compress(FILE *in, gzFile out) {
local char buf[BUFLEN];
int len;
int err;
@@ -366,7 +366,7 @@ void gz_compress(FILE *in, gzFile out) {
/* ===========================================================================
* Uncompress input to output then close both files.
*/
-void gz_uncompress(gzFile in, FILE *out) {
+static void gz_uncompress(gzFile in, FILE *out) {
local char buf[BUFLEN];
int len;
int err;
@@ -390,7 +390,7 @@ void gz_uncompress(gzFile in, FILE *out) {
* Compress the given file: create a corresponding .gz file and remove the
* original.
*/
-void file_compress(char *file, char *mode) {
+static void file_compress(char *file, char *mode) {
local char outfile[MAX_NAME_LEN];
FILE *in;
gzFile out;
@@ -426,7 +426,7 @@ void file_compress(char *file, char *mode) {
/* ===========================================================================
* Uncompress the given file and remove the original.
*/
-void file_uncompress(char *file) {
+static void file_uncompress(char *file) {
local char buf[MAX_NAME_LEN];
char *infile, *outfile;
FILE *out;
diff --git a/src/deps/src/zlib/treebuild.xml b/src/deps/src/zlib/treebuild.xml
index 1d1b00770..930b00be4 100644
--- a/src/deps/src/zlib/treebuild.xml
+++ b/src/deps/src/zlib/treebuild.xml
@@ -1,6 +1,6 @@
-
-
+
+
zip compression library
diff --git a/src/deps/src/zlib/trees.c b/src/deps/src/zlib/trees.c
index 8dbdc40ba..6a523ef34 100644
--- a/src/deps/src/zlib/trees.c
+++ b/src/deps/src/zlib/trees.c
@@ -1,5 +1,5 @@
/* trees.c -- output deflated data using Huffman coding
- * Copyright (C) 1995-2021 Jean-loup Gailly
+ * Copyright (C) 1995-2024 Jean-loup Gailly
* detect_data_type() function provided freely by Cosmin Truta, 2006
* For conditions of distribution and use, see copyright notice in zlib.h
*/
@@ -899,14 +899,19 @@ local void compress_block(deflate_state *s, const ct_data *ltree,
const ct_data *dtree) {
unsigned dist; /* distance of matched string */
int lc; /* match length or unmatched char (if dist == 0) */
- unsigned sx = 0; /* running index in sym_buf */
+ unsigned sx = 0; /* running index in symbol buffers */
unsigned code; /* the code to send */
int extra; /* number of extra bits to send */
if (s->sym_next != 0) do {
+#ifdef LIT_MEM
+ dist = s->d_buf[sx];
+ lc = s->l_buf[sx++];
+#else
dist = s->sym_buf[sx++] & 0xff;
dist += (unsigned)(s->sym_buf[sx++] & 0xff) << 8;
lc = s->sym_buf[sx++];
+#endif
if (dist == 0) {
send_code(s, lc, ltree); /* send a literal byte */
Tracecv(isgraph(lc), (stderr," '%c' ", lc));
@@ -931,8 +936,12 @@ local void compress_block(deflate_state *s, const ct_data *ltree,
}
} /* literal or match pair ? */
- /* Check that the overlay between pending_buf and sym_buf is ok: */
+ /* Check for no overlay of pending_buf on needed symbols */
+#ifdef LIT_MEM
+ Assert(s->pending < 2 * (s->lit_bufsize + sx), "pendingBuf overflow");
+#else
Assert(s->pending < s->lit_bufsize + sx, "pendingBuf overflow");
+#endif
} while (sx < s->sym_next);
@@ -1082,9 +1091,14 @@ void ZLIB_INTERNAL _tr_flush_block(deflate_state *s, charf *buf,
* the current block must be flushed.
*/
int ZLIB_INTERNAL _tr_tally(deflate_state *s, unsigned dist, unsigned lc) {
+#ifdef LIT_MEM
+ s->d_buf[s->sym_next] = (ush)dist;
+ s->l_buf[s->sym_next++] = (uch)lc;
+#else
s->sym_buf[s->sym_next++] = (uch)dist;
s->sym_buf[s->sym_next++] = (uch)(dist >> 8);
s->sym_buf[s->sym_next++] = (uch)lc;
+#endif
if (dist == 0) {
/* lc is the unmatched char */
s->dyn_ltree[lc].Freq++;
diff --git a/src/deps/src/zlib/win32/DLL_FAQ.txt b/src/deps/src/zlib/win32/DLL_FAQ.txt
index 12c009018..d8cf5f31e 100644
--- a/src/deps/src/zlib/win32/DLL_FAQ.txt
+++ b/src/deps/src/zlib/win32/DLL_FAQ.txt
@@ -3,7 +3,7 @@
This document describes the design, the rationale, and the usage
-of the official DLL build of zlib, named ZLIB1.DLL. If you have
+of the common DLL build of zlib, named ZLIB1.DLL. If you have
general questions about zlib, you should see the file "FAQ" found
in the zlib distribution, or at the following location:
http://www.gzip.org/zlib/zlib_faq.html
@@ -11,13 +11,9 @@ in the zlib distribution, or at the following location:
1. What is ZLIB1.DLL, and how can I get it?
- - ZLIB1.DLL is the official build of zlib as a DLL.
+ - ZLIB1.DLL is the common build of zlib as a DLL.
(Please remark the character '1' in the name.)
- Pointers to a precompiled ZLIB1.DLL can be found in the zlib
- web site at:
- http://www.zlib.net/
-
Applications that link to ZLIB1.DLL can rely on the following
specification:
@@ -379,18 +375,6 @@ in the zlib distribution, or at the following location:
code. But you can make your own private DLL build, under a
different file name, as suggested in the previous answer.
-
-17. I made my own ZLIB1.DLL build. Can I test it for compliance?
-
- - We prefer that you download the official DLL from the zlib
- web site. If you need something peculiar from this DLL, you
- can send your suggestion to the zlib mailing list.
-
- However, in case you do rebuild the DLL yourself, you can run
- it with the test programs found in the DLL distribution.
- Running these test programs is not a guarantee of compliance,
- but a failure can imply a detected problem.
-
**
This document is written and maintained by
diff --git a/src/deps/src/zlib/win32/README-WIN32.txt b/src/deps/src/zlib/win32/README-WIN32.txt
index 384c988fa..14e6398ef 100644
--- a/src/deps/src/zlib/win32/README-WIN32.txt
+++ b/src/deps/src/zlib/win32/README-WIN32.txt
@@ -1,6 +1,6 @@
ZLIB DATA COMPRESSION LIBRARY
-zlib 1.3.0 is a general purpose data compression library. All the code is
+zlib 1.3.1 is a general purpose data compression library. All the code is
thread safe. The data format used by the zlib library is described by RFCs
(Request for Comments) 1950 to 1952 in the files
http://www.ietf.org/rfc/rfc1950.txt (zlib format), rfc1951.txt (deflate format)
@@ -16,13 +16,13 @@ is http://zlib.net/ . Before reporting a problem, please check this site to
verify that you have the latest version of zlib; otherwise get the latest
version and check whether the problem still exists or not.
-PLEASE read DLL_FAQ.txt, and the the zlib FAQ http://zlib.net/zlib_faq.html
-before asking for help.
+PLEASE read DLL_FAQ.txt, and the zlib FAQ http://zlib.net/zlib_faq.html before
+asking for help.
Manifest:
-The package zlib-1.3.0-win32-x86.zip will contain the following files:
+The package zlib-1.3.1-win32-x86.zip will contain the following files:
README-WIN32.txt This document
ChangeLog Changes since previous zlib packages
diff --git a/src/deps/src/zlib/zconf.h b/src/deps/src/zlib/zconf.h
index fb76ffe31..62adc8d84 100644
--- a/src/deps/src/zlib/zconf.h
+++ b/src/deps/src/zlib/zconf.h
@@ -1,5 +1,5 @@
/* zconf.h -- configuration of the zlib compression library
- * Copyright (C) 1995-2016 Jean-loup Gailly, Mark Adler
+ * Copyright (C) 1995-2024 Jean-loup Gailly, Mark Adler
* For conditions of distribution and use, see copyright notice in zlib.h
*/
@@ -300,14 +300,6 @@
# endif
#endif
-#ifndef Z_ARG /* function prototypes for stdarg */
-# if defined(STDC) || defined(Z_HAVE_STDARG_H)
-# define Z_ARG(args) args
-# else
-# define Z_ARG(args) ()
-# endif
-#endif
-
/* The following definitions for FAR are needed only for MSDOS mixed
* model programming (small or medium model with some far allocations).
* This was tested only with MSC; for other MSDOS compilers you may have
diff --git a/src/deps/src/zlib/zconf.h.cmakein b/src/deps/src/zlib/zconf.h.cmakein
index 310c43928..0abe3bc9d 100644
--- a/src/deps/src/zlib/zconf.h.cmakein
+++ b/src/deps/src/zlib/zconf.h.cmakein
@@ -1,5 +1,5 @@
/* zconf.h -- configuration of the zlib compression library
- * Copyright (C) 1995-2016 Jean-loup Gailly, Mark Adler
+ * Copyright (C) 1995-2024 Jean-loup Gailly, Mark Adler
* For conditions of distribution and use, see copyright notice in zlib.h
*/
@@ -302,14 +302,6 @@
# endif
#endif
-#ifndef Z_ARG /* function prototypes for stdarg */
-# if defined(STDC) || defined(Z_HAVE_STDARG_H)
-# define Z_ARG(args) args
-# else
-# define Z_ARG(args) ()
-# endif
-#endif
-
/* The following definitions for FAR are needed only for MSDOS mixed
* model programming (small or medium model with some far allocations).
* This was tested only with MSC; for other MSDOS compilers you may have
diff --git a/src/deps/src/zlib/zconf.h.in b/src/deps/src/zlib/zconf.h.in
index fb76ffe31..62adc8d84 100644
--- a/src/deps/src/zlib/zconf.h.in
+++ b/src/deps/src/zlib/zconf.h.in
@@ -1,5 +1,5 @@
/* zconf.h -- configuration of the zlib compression library
- * Copyright (C) 1995-2016 Jean-loup Gailly, Mark Adler
+ * Copyright (C) 1995-2024 Jean-loup Gailly, Mark Adler
* For conditions of distribution and use, see copyright notice in zlib.h
*/
@@ -300,14 +300,6 @@
# endif
#endif
-#ifndef Z_ARG /* function prototypes for stdarg */
-# if defined(STDC) || defined(Z_HAVE_STDARG_H)
-# define Z_ARG(args) args
-# else
-# define Z_ARG(args) ()
-# endif
-#endif
-
/* The following definitions for FAR are needed only for MSDOS mixed
* model programming (small or medium model with some far allocations).
* This was tested only with MSC; for other MSDOS compilers you may have
diff --git a/src/deps/src/zlib/zlib.3 b/src/deps/src/zlib/zlib.3
index 4dd289675..c716020ea 100644
--- a/src/deps/src/zlib/zlib.3
+++ b/src/deps/src/zlib/zlib.3
@@ -1,4 +1,4 @@
-.TH ZLIB 3 "18 Aug 2023"
+.TH ZLIB 3 "22 Jan 2024"
.SH NAME
zlib \- compression/decompression library
.SH SYNOPSIS
@@ -105,9 +105,9 @@ before asking for help.
Send questions and/or comments to zlib@gzip.org,
or (for the Windows DLL version) to Gilles Vollant (info@winimage.com).
.SH AUTHORS AND LICENSE
-Version 1.3
+Version 1.3.1
.LP
-Copyright (C) 1995-2023 Jean-loup Gailly and Mark Adler
+Copyright (C) 1995-2024 Jean-loup Gailly and Mark Adler
.LP
This software is provided 'as-is', without any express or implied
warranty. In no event will the authors be held liable for any damages
diff --git a/src/deps/src/zlib/zlib.3.pdf b/src/deps/src/zlib/zlib.3.pdf
index da12d3718..b224532bd 100644
Binary files a/src/deps/src/zlib/zlib.3.pdf and b/src/deps/src/zlib/zlib.3.pdf differ
diff --git a/src/deps/src/zlib/zlib.h b/src/deps/src/zlib/zlib.h
index 6b7244f99..8d4b932ea 100644
--- a/src/deps/src/zlib/zlib.h
+++ b/src/deps/src/zlib/zlib.h
@@ -1,7 +1,7 @@
/* zlib.h -- interface of the 'zlib' general purpose compression library
- version 1.3, August 18th, 2023
+ version 1.3.1, January 22nd, 2024
- Copyright (C) 1995-2023 Jean-loup Gailly and Mark Adler
+ Copyright (C) 1995-2024 Jean-loup Gailly and Mark Adler
This software is provided 'as-is', without any express or implied
warranty. In no event will the authors be held liable for any damages
@@ -37,11 +37,11 @@
extern "C" {
#endif
-#define ZLIB_VERSION "1.3"
-#define ZLIB_VERNUM 0x1300
+#define ZLIB_VERSION "1.3.1"
+#define ZLIB_VERNUM 0x1310
#define ZLIB_VER_MAJOR 1
#define ZLIB_VER_MINOR 3
-#define ZLIB_VER_REVISION 0
+#define ZLIB_VER_REVISION 1
#define ZLIB_VER_SUBREVISION 0
/*
@@ -936,10 +936,10 @@ ZEXTERN int ZEXPORT inflateSync(z_streamp strm);
inflateSync returns Z_OK if a possible full flush point has been found,
Z_BUF_ERROR if no more input was provided, Z_DATA_ERROR if no flush point
has been found, or Z_STREAM_ERROR if the stream structure was inconsistent.
- In the success case, the application may save the current current value of
- total_in which indicates where valid compressed data was found. In the
- error case, the application may repeatedly call inflateSync, providing more
- input each time, until success or end of the input data.
+ In the success case, the application may save the current value of total_in
+ which indicates where valid compressed data was found. In the error case,
+ the application may repeatedly call inflateSync, providing more input each
+ time, until success or end of the input data.
*/
ZEXTERN int ZEXPORT inflateCopy(z_streamp dest,
@@ -1758,14 +1758,14 @@ ZEXTERN uLong ZEXPORT crc32_combine(uLong crc1, uLong crc2, z_off_t len2);
seq1 and seq2 with lengths len1 and len2, CRC-32 check values were
calculated for each, crc1 and crc2. crc32_combine() returns the CRC-32
check value of seq1 and seq2 concatenated, requiring only crc1, crc2, and
- len2.
+ len2. len2 must be non-negative.
*/
/*
ZEXTERN uLong ZEXPORT crc32_combine_gen(z_off_t len2);
Return the operator corresponding to length len2, to be used with
- crc32_combine_op().
+ crc32_combine_op(). len2 must be non-negative.
*/
ZEXTERN uLong ZEXPORT crc32_combine_op(uLong crc1, uLong crc2, uLong op);
diff --git a/src/deps/src/zlib/zlib.map b/src/deps/src/zlib/zlib.map
index b330b606f..31544f2e9 100644
--- a/src/deps/src/zlib/zlib.map
+++ b/src/deps/src/zlib/zlib.map
@@ -1,100 +1,100 @@
-ZLIB_1.2.0 {
- global:
- compressBound;
- deflateBound;
- inflateBack;
- inflateBackEnd;
- inflateBackInit_;
- inflateCopy;
- local:
- deflate_copyright;
- inflate_copyright;
- inflate_fast;
- inflate_table;
- zcalloc;
- zcfree;
- z_errmsg;
- gz_error;
- gz_intmax;
- _*;
-};
-
-ZLIB_1.2.0.2 {
- gzclearerr;
- gzungetc;
- zlibCompileFlags;
-} ZLIB_1.2.0;
-
-ZLIB_1.2.0.8 {
- deflatePrime;
-} ZLIB_1.2.0.2;
-
-ZLIB_1.2.2 {
- adler32_combine;
- crc32_combine;
- deflateSetHeader;
- inflateGetHeader;
-} ZLIB_1.2.0.8;
-
-ZLIB_1.2.2.3 {
- deflateTune;
- gzdirect;
-} ZLIB_1.2.2;
-
-ZLIB_1.2.2.4 {
- inflatePrime;
-} ZLIB_1.2.2.3;
-
-ZLIB_1.2.3.3 {
- adler32_combine64;
- crc32_combine64;
- gzopen64;
- gzseek64;
- gztell64;
- inflateUndermine;
-} ZLIB_1.2.2.4;
-
-ZLIB_1.2.3.4 {
- inflateReset2;
- inflateMark;
-} ZLIB_1.2.3.3;
-
-ZLIB_1.2.3.5 {
- gzbuffer;
- gzoffset;
- gzoffset64;
- gzclose_r;
- gzclose_w;
-} ZLIB_1.2.3.4;
-
-ZLIB_1.2.5.1 {
- deflatePending;
-} ZLIB_1.2.3.5;
-
-ZLIB_1.2.5.2 {
- deflateResetKeep;
- gzgetc_;
- inflateResetKeep;
-} ZLIB_1.2.5.1;
-
-ZLIB_1.2.7.1 {
- inflateGetDictionary;
- gzvprintf;
-} ZLIB_1.2.5.2;
-
-ZLIB_1.2.9 {
- inflateCodesUsed;
- inflateValidate;
- uncompress2;
- gzfread;
- gzfwrite;
- deflateGetDictionary;
- adler32_z;
- crc32_z;
-} ZLIB_1.2.7.1;
-
-ZLIB_1.2.12 {
- crc32_combine_gen;
- crc32_combine_gen64;
- crc32_combine_op;
-} ZLIB_1.2.9;
+ZLIB_1.2.0 {
+ global:
+ compressBound;
+ deflateBound;
+ inflateBack;
+ inflateBackEnd;
+ inflateBackInit_;
+ inflateCopy;
+ local:
+ deflate_copyright;
+ inflate_copyright;
+ inflate_fast;
+ inflate_table;
+ zcalloc;
+ zcfree;
+ z_errmsg;
+ gz_error;
+ gz_intmax;
+ _*;
+};
+
+ZLIB_1.2.0.2 {
+ gzclearerr;
+ gzungetc;
+ zlibCompileFlags;
+} ZLIB_1.2.0;
+
+ZLIB_1.2.0.8 {
+ deflatePrime;
+} ZLIB_1.2.0.2;
+
+ZLIB_1.2.2 {
+ adler32_combine;
+ crc32_combine;
+ deflateSetHeader;
+ inflateGetHeader;
+} ZLIB_1.2.0.8;
+
+ZLIB_1.2.2.3 {
+ deflateTune;
+ gzdirect;
+} ZLIB_1.2.2;
+
+ZLIB_1.2.2.4 {
+ inflatePrime;
+} ZLIB_1.2.2.3;
+
+ZLIB_1.2.3.3 {
+ adler32_combine64;
+ crc32_combine64;
+ gzopen64;
+ gzseek64;
+ gztell64;
+ inflateUndermine;
+} ZLIB_1.2.2.4;
+
+ZLIB_1.2.3.4 {
+ inflateReset2;
+ inflateMark;
+} ZLIB_1.2.3.3;
+
+ZLIB_1.2.3.5 {
+ gzbuffer;
+ gzoffset;
+ gzoffset64;
+ gzclose_r;
+ gzclose_w;
+} ZLIB_1.2.3.4;
+
+ZLIB_1.2.5.1 {
+ deflatePending;
+} ZLIB_1.2.3.5;
+
+ZLIB_1.2.5.2 {
+ deflateResetKeep;
+ gzgetc_;
+ inflateResetKeep;
+} ZLIB_1.2.5.1;
+
+ZLIB_1.2.7.1 {
+ inflateGetDictionary;
+ gzvprintf;
+} ZLIB_1.2.5.2;
+
+ZLIB_1.2.9 {
+ inflateCodesUsed;
+ inflateValidate;
+ uncompress2;
+ gzfread;
+ gzfwrite;
+ deflateGetDictionary;
+ adler32_z;
+ crc32_z;
+} ZLIB_1.2.7.1;
+
+ZLIB_1.2.12 {
+ crc32_combine_gen;
+ crc32_combine_gen64;
+ crc32_combine_op;
+} ZLIB_1.2.9;
diff --git a/src/deps/src/zlib/zutil.h b/src/deps/src/zlib/zutil.h
index 902a304cc..48dd7feba 100644
--- a/src/deps/src/zlib/zutil.h
+++ b/src/deps/src/zlib/zutil.h
@@ -1,5 +1,5 @@
/* zutil.h -- internal interface and configuration of the compression library
- * Copyright (C) 1995-2022 Jean-loup Gailly, Mark Adler
+ * Copyright (C) 1995-2024 Jean-loup Gailly, Mark Adler
* For conditions of distribution and use, see copyright notice in zlib.h
*/
@@ -56,7 +56,7 @@ typedef unsigned long ulg;
extern z_const char * const z_errmsg[10]; /* indexed by 2-zlib_error */
/* (size given to avoid silly warnings with Visual C++) */
-#define ERR_MSG(err) z_errmsg[Z_NEED_DICT-(err)]
+#define ERR_MSG(err) z_errmsg[(err) < -6 || (err) > 2 ? 9 : 2 - (err)]
#define ERR_RETURN(strm,err) \
return (strm->msg = ERR_MSG(err), (err))
@@ -137,17 +137,8 @@ extern z_const char * const z_errmsg[10]; /* indexed by 2-zlib_error */
# endif
#endif
-#if defined(MACOS) || defined(TARGET_OS_MAC)
+#if defined(MACOS)
# define OS_CODE 7
-# ifndef Z_SOLO
-# if defined(__MWERKS__) && __dest_os != __be_os && __dest_os != __win32_os
-# include /* for fdopen */
-# else
-# ifndef fdopen
-# define fdopen(fd,mode) NULL /* No fdopen() */
-# endif
-# endif
-# endif
#endif
#ifdef __acorn
@@ -170,18 +161,6 @@ extern z_const char * const z_errmsg[10]; /* indexed by 2-zlib_error */
# define OS_CODE 19
#endif
-#if defined(_BEOS_) || defined(RISCOS)
-# define fdopen(fd,mode) NULL /* No fdopen() */
-#endif
-
-#if (defined(_MSC_VER) && (_MSC_VER > 600)) && !defined __INTERIX
-# if defined(_WIN32_WCE)
-# define fdopen(fd,mode) NULL /* No fdopen() */
-# else
-# define fdopen(fd,type) _fdopen(fd,type)
-# endif
-#endif
-
#if defined(__BORLANDC__) && !defined(MSDOS)
#pragma warn -8004
#pragma warn -8008
diff --git a/src/scheduler/Dockerfile b/src/scheduler/Dockerfile
index db1478f50..f27e57c83 100644
--- a/src/scheduler/Dockerfile
+++ b/src/scheduler/Dockerfile
@@ -1,4 +1,4 @@
-FROM python:3.12.1-alpine3.18@sha256:af0d8da43677e3000ebdf4045508d891a87e7bd2d3ec87bc6e40403be97291b8 AS builder
+FROM python:3.12.1-alpine3.18@sha256:fb759579d60cfe1f70b110a27be95aaa7cf758d2fa21cf54fffb71c2ba3f8034 AS builder
# Install python dependencies
RUN apk add --no-cache --virtual .build-deps g++ gcc musl-dev jpeg-dev zlib-dev libffi-dev cairo-dev pango-dev gdk-pixbuf-dev openssl-dev cargo postgresql-dev
@@ -38,7 +38,7 @@ COPY src/common/utils utils
COPY src/scheduler scheduler
COPY src/VERSION VERSION
-FROM python:3.12.1-alpine3.18@sha256:af0d8da43677e3000ebdf4045508d891a87e7bd2d3ec87bc6e40403be97291b8
+FROM python:3.12.1-alpine3.18@sha256:fb759579d60cfe1f70b110a27be95aaa7cf758d2fa21cf54fffb71c2ba3f8034
# Set default umask to prevent huge recursive chmod increasing the final image size
RUN umask 027
@@ -77,7 +77,7 @@ COPY --chown=root:scheduler src/bw/misc/country.mmdb /var/tmp/bunkerweb/country.
RUN chmod 770 /var/tmp/bunkerweb/asn.mmdb /var/tmp/bunkerweb/country.mmdb
# Fix CVEs
-RUN apk add --no-cache "libcrypto3>=3.1.4-r3" "libssl3>=3.1.4-r3"
+RUN apk add --no-cache "sqlite-libs>=3.41.2-r3"
VOLUME /data /etc/nginx
diff --git a/src/scheduler/main.py b/src/scheduler/main.py
index 2bbc2a590..ffb0046aa 100644
--- a/src/scheduler/main.py
+++ b/src/scheduler/main.py
@@ -282,7 +282,7 @@ if __name__ == "__main__":
env["DATABASE_URI"] = db.database_uri
# Instantiate scheduler
- SCHEDULER = JobScheduler(env.copy() | environ.copy(), logger, INTEGRATION, db=db)
+ SCHEDULER = JobScheduler(env | environ.copy(), logger, INTEGRATION, db=db)
if INTEGRATION in ("Docker", "Swarm", "Kubernetes", "Autoconf"):
# Automatically setup the scheduler apis
@@ -464,7 +464,7 @@ if __name__ == "__main__":
if RUN_JOBS_ONCE:
# Update the environment variables of the scheduler
- SCHEDULER.env = env.copy() | environ.copy()
+ SCHEDULER.env = env | environ.copy()
SCHEDULER.setup()
# Only run jobs once
diff --git a/src/scheduler/requirements.in b/src/scheduler/requirements.in
index 90385e1dc..c1bd73ddf 100644
--- a/src/scheduler/requirements.in
+++ b/src/scheduler/requirements.in
@@ -1,7 +1,6 @@
certbot==2.8.0
configobj==5.0.8
-cryptography==41.0.7
+cryptography==42.0.0
maxminddb==2.5.2
python-magic==0.4.27
schedule==1.2.1
-urllib3<2.0.0
diff --git a/src/scheduler/requirements.txt b/src/scheduler/requirements.txt
index 8e4d628e4..0779fbdc3 100644
--- a/src/scheduler/requirements.txt
+++ b/src/scheduler/requirements.txt
@@ -172,30 +172,39 @@ configobj==5.0.8 \
# via
# -r requirements.in
# certbot
-cryptography==41.0.7 \
- --hash=sha256:079b85658ea2f59c4f43b70f8119a52414cdb7be34da5d019a77bf96d473b960 \
- --hash=sha256:09616eeaef406f99046553b8a40fbf8b1e70795a91885ba4c96a70793de5504a \
- --hash=sha256:13f93ce9bea8016c253b34afc6bd6a75993e5c40672ed5405a9c832f0d4a00bc \
- --hash=sha256:37a138589b12069efb424220bf78eac59ca68b95696fc622b6ccc1c0a197204a \
- --hash=sha256:3c78451b78313fa81607fa1b3f1ae0a5ddd8014c38a02d9db0616133987b9cdf \
- --hash=sha256:43f2552a2378b44869fe8827aa19e69512e3245a219104438692385b0ee119d1 \
- --hash=sha256:48a0476626da912a44cc078f9893f292f0b3e4c739caf289268168d8f4702a39 \
- --hash=sha256:49f0805fc0b2ac8d4882dd52f4a3b935b210935d500b6b805f321addc8177406 \
- --hash=sha256:5429ec739a29df2e29e15d082f1d9ad683701f0ec7709ca479b3ff2708dae65a \
- --hash=sha256:5a1b41bc97f1ad230a41657d9155113c7521953869ae57ac39ac7f1bb471469a \
- --hash=sha256:68a2dec79deebc5d26d617bfdf6e8aab065a4f34934b22d3b5010df3ba36612c \
- --hash=sha256:7a698cb1dac82c35fcf8fe3417a3aaba97de16a01ac914b89a0889d364d2f6be \
- --hash=sha256:841df4caa01008bad253bce2a6f7b47f86dc9f08df4b433c404def869f590a15 \
- --hash=sha256:90452ba79b8788fa380dfb587cca692976ef4e757b194b093d845e8d99f612f2 \
- --hash=sha256:928258ba5d6f8ae644e764d0f996d61a8777559f72dfeb2eea7e2fe0ad6e782d \
- --hash=sha256:af03b32695b24d85a75d40e1ba39ffe7db7ffcb099fe507b39fd41a565f1b157 \
- --hash=sha256:b640981bf64a3e978a56167594a0e97db71c89a479da8e175d8bb5be5178c003 \
- --hash=sha256:c5ca78485a255e03c32b513f8c2bc39fedb7f5c5f8535545bdc223a03b24f248 \
- --hash=sha256:c7f3201ec47d5207841402594f1d7950879ef890c0c495052fa62f58283fde1a \
- --hash=sha256:d5ec85080cce7b0513cfd233914eb8b7bbd0633f1d1703aa28d1dd5a72f678ec \
- --hash=sha256:d6c391c021ab1f7a82da5d8d0b3cee2f4b2c455ec86c8aebbc84837a631ff309 \
- --hash=sha256:e3114da6d7f95d2dee7d3f4eec16dacff819740bbab931aff8648cb13c5ff5e7 \
- --hash=sha256:f983596065a18a2183e7f79ab3fd4c475205b839e02cbc0efbbf9666c4b3083d
+cryptography==42.0.0 \
+ --hash=sha256:0a68bfcf57a6887818307600c3c0ebc3f62fbb6ccad2240aa21887cda1f8df1b \
+ --hash=sha256:146e971e92a6dd042214b537a726c9750496128453146ab0ee8971a0299dc9bd \
+ --hash=sha256:14e4b909373bc5bf1095311fa0f7fcabf2d1a160ca13f1e9e467be1ac4cbdf94 \
+ --hash=sha256:206aaf42e031b93f86ad60f9f5d9da1b09164f25488238ac1dc488334eb5e221 \
+ --hash=sha256:3005166a39b70c8b94455fdbe78d87a444da31ff70de3331cdec2c568cf25b7e \
+ --hash=sha256:324721d93b998cb7367f1e6897370644751e5580ff9b370c0a50dc60a2003513 \
+ --hash=sha256:33588310b5c886dfb87dba5f013b8d27df7ffd31dc753775342a1e5ab139e59d \
+ --hash=sha256:35cf6ed4c38f054478a9df14f03c1169bb14bd98f0b1705751079b25e1cb58bc \
+ --hash=sha256:3ca482ea80626048975360c8e62be3ceb0f11803180b73163acd24bf014133a0 \
+ --hash=sha256:56ce0c106d5c3fec1038c3cca3d55ac320a5be1b44bf15116732d0bc716979a2 \
+ --hash=sha256:5a217bca51f3b91971400890905a9323ad805838ca3fa1e202a01844f485ee87 \
+ --hash=sha256:678cfa0d1e72ef41d48993a7be75a76b0725d29b820ff3cfd606a5b2b33fda01 \
+ --hash=sha256:69fd009a325cad6fbfd5b04c711a4da563c6c4854fc4c9544bff3088387c77c0 \
+ --hash=sha256:6cf9b76d6e93c62114bd19485e5cb003115c134cf9ce91f8ac924c44f8c8c3f4 \
+ --hash=sha256:74f18a4c8ca04134d2052a140322002fef535c99cdbc2a6afc18a8024d5c9d5b \
+ --hash=sha256:85f759ed59ffd1d0baad296e72780aa62ff8a71f94dc1ab340386a1207d0ea81 \
+ --hash=sha256:87086eae86a700307b544625e3ba11cc600c3c0ef8ab97b0fda0705d6db3d4e3 \
+ --hash=sha256:8814722cffcfd1fbd91edd9f3451b88a8f26a5fd41b28c1c9193949d1c689dc4 \
+ --hash=sha256:8fedec73d590fd30c4e3f0d0f4bc961aeca8390c72f3eaa1a0874d180e868ddf \
+ --hash=sha256:9515ea7f596c8092fdc9902627e51b23a75daa2c7815ed5aa8cf4f07469212ec \
+ --hash=sha256:988b738f56c665366b1e4bfd9045c3efae89ee366ca3839cd5af53eaa1401bce \
+ --hash=sha256:a2a8d873667e4fd2f34aedab02ba500b824692c6542e017075a2efc38f60a4c0 \
+ --hash=sha256:bd7cf7a8d9f34cc67220f1195884151426ce616fdc8285df9054bfa10135925f \
+ --hash=sha256:bdce70e562c69bb089523e75ef1d9625b7417c6297a76ac27b1b8b1eb51b7d0f \
+ --hash=sha256:be14b31eb3a293fc6e6aa2807c8a3224c71426f7c4e3639ccf1a2f3ffd6df8c3 \
+ --hash=sha256:be41b0c7366e5549265adf2145135dca107718fa44b6e418dc7499cfff6b4689 \
+ --hash=sha256:c310767268d88803b653fffe6d6f2f17bb9d49ffceb8d70aed50ad45ea49ab08 \
+ --hash=sha256:c58115384bdcfe9c7f644c72f10f6f42bed7cf59f7b52fe1bf7ae0a622b3a139 \
+ --hash=sha256:c640b0ef54138fde761ec99a6c7dc4ce05e80420262c20fa239e694ca371d434 \
+ --hash=sha256:ca20550bb590db16223eb9ccc5852335b48b8f597e2f6f0878bbfd9e7314eb17 \
+ --hash=sha256:d97aae66b7de41cdf5b12087b5509e4e9805ed6f562406dfcf60e8481a9a28f8 \
+ --hash=sha256:e9326ca78111e4c645f7e49cbce4ed2f3f85e17b61a563328c85a5208cf34440
# via
# -r requirements.in
# acme
@@ -278,9 +287,9 @@ pycparser==2.21 \
--hash=sha256:8ee45429555515e1f6b185e78100aea234072576aa43ab53aefcae078162fca9 \
--hash=sha256:e644fdec12f7872f86c58ff790da456218b10f863970249516d60a5eaca77206
# via cffi
-pyopenssl==23.3.0 \
- --hash=sha256:6756834481d9ed5470f4a9393455154bc92fe7a64b7bc6ee2c804e78c52099b2 \
- --hash=sha256:6b2cba5cc46e822750ec3e5a81ee12819850b11303630d575e98108a079c2b12
+pyopenssl==24.0.0 \
+ --hash=sha256:6aa33039a93fffa4563e655b61d11364d01264be8ccb49906101e02a334530bf \
+ --hash=sha256:ba07553fb6fd6a7a2259adb9b84e12302a9a8a75c44046e8bb5d3e5ee887e3c3
# via
# acme
# josepy
@@ -319,12 +328,10 @@ six==1.16.0 \
--hash=sha256:1e61c37477a1626458e36f7b1d82aa5c9b094fa4802892072e49de9c60c4c926 \
--hash=sha256:8abb2f1d86890a2dfb989f9a77cfcfd3e47c2a354b01111771326f8aa26e0254
# via configobj
-urllib3==1.26.18 \
- --hash=sha256:34b97092d7e0a3a8cf7cd10e386f401b3737364026c45e622aa02903dffe0f07 \
- --hash=sha256:f8ecc1bba5667413457c529ab955bf8c67b45db799d159066261719e328580a0
- # via
- # -r requirements.in
- # requests
+urllib3==2.1.0 \
+ --hash=sha256:55901e917a5896a349ff771be919f8bd99aff50b79fe58fec595eb37bbc56bb3 \
+ --hash=sha256:df7aa8afb0148fa78488e7899b2c59b5f4ffcfa82e6c54ccb9dd37c1d7b52d54
+ # via requests
zipp==3.17.0 \
--hash=sha256:0e923e726174922dce09c53c59ad483ff7bbb8e572e00c7f7c46b88556409f31 \
--hash=sha256:84e64a1c28cf7e91ed2078bb8cc8c259cb19b76942096c8d7b84947690cabaf0
diff --git a/src/ui/Dockerfile b/src/ui/Dockerfile
index 71d92dd9b..9888a432d 100644
--- a/src/ui/Dockerfile
+++ b/src/ui/Dockerfile
@@ -1,4 +1,4 @@
-FROM python:3.12.1-alpine3.18@sha256:af0d8da43677e3000ebdf4045508d891a87e7bd2d3ec87bc6e40403be97291b8 AS builder
+FROM python:3.12.1-alpine3.18@sha256:fb759579d60cfe1f70b110a27be95aaa7cf758d2fa21cf54fffb71c2ba3f8034 AS builder
# Install python dependencies
RUN apk add --no-cache --virtual .build-deps g++ gcc musl-dev jpeg-dev zlib-dev libffi-dev cairo-dev pango-dev gdk-pixbuf-dev openssl-dev cargo postgresql-dev file make
@@ -36,7 +36,7 @@ COPY src/common/helpers helpers
COPY src/ui ui
COPY src/VERSION VERSION
-FROM python:3.12.1-alpine3.18@sha256:af0d8da43677e3000ebdf4045508d891a87e7bd2d3ec87bc6e40403be97291b8
+FROM python:3.12.1-alpine3.18@sha256:fb759579d60cfe1f70b110a27be95aaa7cf758d2fa21cf54fffb71c2ba3f8034
# Set default umask to prevent huge recursive chmod increasing the final image size
RUN umask 027
@@ -70,7 +70,7 @@ RUN apk add --no-cache bash && \
ln -s /proc/1/fd/2 /var/log/bunkerweb/ui.log
# Fix CVEs
-RUN apk add --no-cache "libcrypto3>=3.1.4-r3" "libssl3>=3.1.4-r3"
+RUN apk add --no-cache "libcrypto3>=3.1.4-r3" "libssl3>=3.1.4-r3" "sqlite-libs>=3.41.2-r3"
VOLUME /data /etc/nginx
diff --git a/src/ui/main.py b/src/ui/main.py
index 9eee65d9f..ac3ea1840 100755
--- a/src/ui/main.py
+++ b/src/ui/main.py
@@ -1,6 +1,7 @@
#!/usr/bin/env python3
from contextlib import suppress
+from math import floor
from os import _exit, getenv, listdir, sep, urandom
from os.path import basename, dirname, join
from secrets import choice
@@ -30,6 +31,7 @@ from jinja2 import Template
from kubernetes import client as kube_client
from kubernetes import config as kube_config
from kubernetes.client.exceptions import ApiException as kube_ApiException
+from redis import Redis, Sentinel
from regex import compile as re_compile, match as regex_match
from requests import get
from shutil import move, rmtree
@@ -48,7 +50,7 @@ from src.Config import Config
from src.ReverseProxied import ReverseProxied
from src.User import AnonymousUser, User
-from utils import check_settings, get_b64encoded_qr_image, path_to_dict
+from utils import check_settings, get_b64encoded_qr_image, path_to_dict, get_remain
from Database import Database # type: ignore
from logging import getLogger
@@ -1595,6 +1597,234 @@ def logs_container(container_id):
return jsonify({"logs": logs, "last_update": int(time() * 1000)})
+@app.route("/reports", methods=["GET"])
+@login_required
+def reports():
+ reports = app.config["INSTANCES"].get_reports()
+ total_reports = len(reports)
+ reports = reports[:100]
+
+ # Prepare data
+ reasons = {}
+ codes = {}
+ for i, report in enumerate(deepcopy(reports)):
+ reports[i]["date"] = datetime.fromtimestamp(floor(reports[i]["date"])).strftime("%d/%m/%Y %H:%M:%S")
+ # Get top reasons
+ if not report["reason"] in reasons:
+ reasons[report["reason"]] = 0
+ reasons[report["reason"]] = reasons[report["reason"]] + 1
+ # Get top status code
+ if not report["status"] in codes:
+ codes[report["status"]] = 0
+ codes[report["status"]] = codes[report["status"]] + 1
+
+ top_reason = ([k for k, v in reasons.items() if v == max(reasons.values())] or [""])[0]
+ top_code = ([k for k, v in codes.items() if v == max(codes.values())] or [""])[0]
+
+ return render_template(
+ "reports.html",
+ reports=reports,
+ total_reports=total_reports,
+ top_code=top_code,
+ top_reason=top_reason,
+ username=current_user.get_id(),
+ dark_mode=app.config["DARK_MODE"],
+ )
+
+
+@app.route("/bans", methods=["GET", "POST"])
+@login_required
+def bans():
+ redis_client = None
+ db_config = app.config["CONFIG"].get_config(methods=False)
+ use_redis = db_config.get("USE_REDIS", "no") == "yes"
+ redis_host = db_config.get("REDIS_HOST")
+ if use_redis and redis_host:
+ redis_port = db_config.get("REDIS_PORT", "6379")
+ if not redis_port.isdigit():
+ redis_port = "6379"
+ redis_port = int(redis_port)
+
+ redis_db = db_config.get("REDIS_DB", "0")
+ if not redis_db.isdigit():
+ redis_db = "0"
+ redis_db = int(redis_db)
+
+ redis_timeout = db_config.get("REDIS_TIMEOUT", "1000.0")
+ try:
+ redis_timeout = float(redis_timeout)
+ except ValueError:
+ redis_timeout = 1000.0
+
+ redis_keepalive_pool = db_config.get("REDIS_KEEPALIVE_POOL", "10")
+ if not redis_keepalive_pool.isdigit():
+ redis_keepalive_pool = "10"
+ redis_keepalive_pool = int(redis_keepalive_pool)
+
+ redis_ssl = db_config.get("REDIS_SSL", "no") == "yes"
+ username = db_config.get("REDIS_USERNAME", None) or None
+ password = db_config.get("REDIS_PASSWORD", None) or None
+ sentinel_hosts = db_config.get("REDIS_SENTINEL_HOSTS", [])
+
+ if isinstance(sentinel_hosts, str):
+ sentinel_hosts = [host.split(":") if ":" in host else host for host in sentinel_hosts.split(" ") if host]
+
+ if sentinel_hosts:
+ sentinel_username = db_config.get("REDIS_SENTINEL_USERNAME", None) or None
+ sentinel_password = db_config.get("REDIS_SENTINEL_PASSWORD", None) or None
+ sentinel_master = db_config.get("REDIS_SENTINEL_MASTER", "")
+
+ sentinel = Sentinel(
+ sentinel_hosts,
+ username=sentinel_username,
+ password=sentinel_password,
+ ssl=redis_ssl,
+ socket_timeout=redis_timeout,
+ socket_connect_timeout=redis_timeout,
+ socket_keepalive=True,
+ max_connections=redis_keepalive_pool,
+ )
+ redis_client = sentinel.slave_for(sentinel_master, db=redis_db, username=username, password=password)
+ else:
+ redis_client = Redis(
+ host=redis_host,
+ port=redis_port,
+ db=redis_db,
+ username=username,
+ password=password,
+ socket_timeout=redis_timeout,
+ socket_connect_timeout=redis_timeout,
+ socket_keepalive=True,
+ max_connections=redis_keepalive_pool,
+ ssl=redis_ssl,
+ )
+
+ try:
+ redis_client.ping()
+ except BaseException:
+ redis_client = None
+ flash("Couldn't connect to redis, ban list might be incomplete", "error")
+
+ if request.method == "POST":
+ # Check variables
+ if not request.form:
+ flash("Missing form data.", "error")
+ return redirect(url_for("bans"))
+
+ if "operation" not in request.form:
+ flash("Operation unknown", "error")
+ return redirect(url_for("bans"))
+
+ if "data" not in request.form:
+ flash("No data to proceed", "error")
+ return redirect(url_for("bans"))
+
+ try:
+ data = json_loads(request.form["data"])
+ assert isinstance(data, list)
+ except BaseException:
+ app.logger.exception(f"Couldn't load data: {request.form['data']}")
+ flash("Data must be a list of dict", "error")
+ return redirect(url_for("bans"))
+
+ if request.form["operation"] == "unban":
+ for unban in data:
+ try:
+ unban = json_loads(unban.replace('"', '"').replace("'", '"'))
+ except BaseException:
+ flash(f"Invalid unban: {unban}, skipping it ...", "error")
+ app.logger.exception(f"Couldn't unban {unban['ip']}")
+ continue
+
+ if "ip" not in unban:
+ flash(f"Invalid unban: {unban}, skipping it ...", "error")
+ continue
+
+ if redis_client:
+ if not redis_client.delete(f"bans_ip_{unban['ip']}"):
+ flash(f"Couldn't unban {unban['ip']} on redis", "error")
+
+ resp = app.config["INSTANCES"].unban(unban["ip"])
+ if resp:
+ flash(f"Couldn't unban {unban['ip']} on the following instances: {', '.join(resp)}", "error")
+ else:
+ flash(f"Successfully unbanned {unban['ip']}")
+ elif request.form["operation"] == "ban":
+ for ban in data:
+ if not isinstance(ban, dict) or "ip" not in ban:
+ flash(f"Invalid ban: {ban}, skipping it ...", "error")
+ continue
+
+ reason = ban.get("reason", "ui")
+ ban_end = 86400.0
+ if "ban_end" in ban:
+ try:
+ ban_end = float(ban["ban_end"])
+ except ValueError:
+ continue
+ ban_end = (datetime.fromtimestamp(ban_end) - datetime.now()).total_seconds()
+
+ if redis_client:
+ ok = redis_client.set(f"bans_ip_{ban['ip']}", dumps({"reason": reason, "date": time()}))
+ if not ok:
+ flash(f"Couldn't ban {ban['ip']} on redis", "error")
+ redis_client.expire(f"bans_ip_{ban['ip']}", int(ban_end))
+
+ resp = app.config["INSTANCES"].ban(ban["ip"], ban_end, reason)
+ if resp:
+ flash(f"Couldn't ban {ban['ip']} on the following instances: {', '.join(resp)}", "error")
+ else:
+ flash(f"Successfully banned {ban['ip']}")
+ else:
+ flash("Operation unknown", "error")
+ return redirect(url_for("bans"))
+
+ return redirect(url_for("loading", next=url_for("bans"), message="Update bans"))
+
+ bans = []
+ if redis_client:
+ for key in redis_client.scan_iter("bans_ip_*"):
+ ip = key.decode("utf-8").replace("bans_ip_", "")
+ data = redis_client.get(key)
+ if not data:
+ continue
+ exp = redis_client.ttl(key)
+ bans.append({"ip": ip, "exp": exp} | json_loads(data)) # type: ignore
+ instance_bans = app.config["INSTANCES"].get_bans()
+
+ # Prepare data
+ reasons = {}
+ timestamp_now = time()
+
+ for ban in instance_bans:
+ if not any(b["ip"] == ban["ip"] for b in bans):
+ bans.append(ban)
+
+ bans = bans[:100]
+
+ for ban in bans:
+ exp = ban.pop("exp")
+ # Add remain
+ ban["remain"], ban["term"] = ("unknown", "unknown") if exp <= 0 else get_remain(exp)
+ # Convert stamp to date
+ ban["ban_start"] = datetime.fromtimestamp(floor(ban["date"])).strftime("%d/%m/%Y %H:%M:%S")
+ ban["ban_end"] = datetime.fromtimestamp(floor(timestamp_now + exp)).strftime("%d/%m/%Y %H:%M:%S")
+ # Get top reason
+ if not ban["reason"] in reasons:
+ reasons[ban["reason"]] = 0
+ reasons[ban["reason"]] = reasons[ban["reason"]] + 1
+
+ top_reason = ([k for k, v in reasons.items() if v == max(reasons.values())] or [""])[0]
+
+ return render_template(
+ "bans.html",
+ bans=bans,
+ top_reason=top_reason,
+ username=current_user.get_id(),
+ dark_mode=app.config["DARK_MODE"],
+ )
+
+
@app.route("/jobs", methods=["GET"])
@login_required
def jobs():
diff --git a/src/ui/requirements.in b/src/ui/requirements.in
index 043c47949..717474531 100644
--- a/src/ui/requirements.in
+++ b/src/ui/requirements.in
@@ -1,6 +1,6 @@
bcrypt==4.1.2
-beautifulsoup4==4.12.2
-Flask==3.0.0
+beautifulsoup4==4.12.3
+Flask==3.0.1
Flask-Login==0.6.3
Flask_WTF==1.2.1
gunicorn[gthread]==21.2.0
diff --git a/src/ui/requirements.txt b/src/ui/requirements.txt
index 9e91d6dd8..d62f6941f 100644
--- a/src/ui/requirements.txt
+++ b/src/ui/requirements.txt
@@ -33,9 +33,9 @@ bcrypt==4.1.2 \
--hash=sha256:f70d9c61f9c4ca7d57f3bfe88a5ccf62546ffbadf3681bb1e268d9d2e41c91a7 \
--hash=sha256:fbe188b878313d01b7718390f31528be4010fed1faa798c5a1d0469c9c48c369
# via -r requirements.in
-beautifulsoup4==4.12.2 \
- --hash=sha256:492bbc69dca35d12daac71c4db1bfff0c876c00ef4a2ffacce226d4638eb72da \
- --hash=sha256:bd2520ca0d9d7d12694a53d44ac482d181b4ec1888909b035a3dbf40d0f57d4a
+beautifulsoup4==4.12.3 \
+ --hash=sha256:74e3d1928edc070d21748185c46e3fb33490f22f52a3addee9aee0f4f7781051 \
+ --hash=sha256:b80878c9f40111313e55da8ba20bdba06d8fa3969fc68304167741bbf9e082ed
# via -r requirements.in
blinker==1.7.0 \
--hash=sha256:c3f865d4d54db7abc53758a01601cf343fe55b84c1de4e3fa910e420b438d5b9 \
@@ -45,9 +45,9 @@ click==8.1.7 \
--hash=sha256:ae74fb96c20a0277a1d615f1e4d73c8414f5a98db8b799a7931d1582f3390c28 \
--hash=sha256:ca9853ad459e787e2192211578cc907e7594e294c7ccc834310722b41b9ca6de
# via flask
-flask==3.0.0 \
- --hash=sha256:21128f47e4e3b9d597a3e8521a329bf56909b690fcc3fa3e477725aa81367638 \
- --hash=sha256:cfadcdb638b609361d29ec22360d6070a77d7463dcb3ab08d2c2f2f168845f58
+flask==3.0.1 \
+ --hash=sha256:6489f51bb3666def6f314e15f19d50a1869a19ae0e8c9a3641ffe66c77d42403 \
+ --hash=sha256:ca631a507f6dfe6c278ae20112cea3ff54ff2216390bf8880f6b035a5354af13
# via
# -r requirements.in
# flask-login
@@ -82,67 +82,67 @@ jinja2==3.1.3 \
--hash=sha256:7d6d50dd97d52cbc355597bd845fabfbac3f551e1f99619e39a35ce8c370b5fa \
--hash=sha256:ac8bd6544d4bb2c9792bf3a159e80bba8fda7f07e81bc3aed565432d5925ba90
# via flask
-markupsafe==2.1.3 \
- --hash=sha256:05fb21170423db021895e1ea1e1f3ab3adb85d1c2333cbc2310f2a26bc77272e \
- --hash=sha256:0a4e4a1aff6c7ac4cd55792abf96c915634c2b97e3cc1c7129578aa68ebd754e \
- --hash=sha256:10bbfe99883db80bdbaff2dcf681dfc6533a614f700da1287707e8a5d78a8431 \
- --hash=sha256:134da1eca9ec0ae528110ccc9e48041e0828d79f24121a1a146161103c76e686 \
- --hash=sha256:14ff806850827afd6b07a5f32bd917fb7f45b046ba40c57abdb636674a8b559c \
- --hash=sha256:1577735524cdad32f9f694208aa75e422adba74f1baee7551620e43a3141f559 \
- --hash=sha256:1b40069d487e7edb2676d3fbdb2b0829ffa2cd63a2ec26c4938b2d34391b4ecc \
- --hash=sha256:1b8dd8c3fd14349433c79fa8abeb573a55fc0fdd769133baac1f5e07abf54aeb \
- --hash=sha256:1f67c7038d560d92149c060157d623c542173016c4babc0c1913cca0564b9939 \
- --hash=sha256:282c2cb35b5b673bbcadb33a585408104df04f14b2d9b01d4c345a3b92861c2c \
- --hash=sha256:2c1b19b3aaacc6e57b7e25710ff571c24d6c3613a45e905b1fde04d691b98ee0 \
- --hash=sha256:2ef12179d3a291be237280175b542c07a36e7f60718296278d8593d21ca937d4 \
- --hash=sha256:338ae27d6b8745585f87218a3f23f1512dbf52c26c28e322dbe54bcede54ccb9 \
- --hash=sha256:3c0fae6c3be832a0a0473ac912810b2877c8cb9d76ca48de1ed31e1c68386575 \
- --hash=sha256:3fd4abcb888d15a94f32b75d8fd18ee162ca0c064f35b11134be77050296d6ba \
- --hash=sha256:42de32b22b6b804f42c5d98be4f7e5e977ecdd9ee9b660fda1a3edf03b11792d \
- --hash=sha256:47d4f1c5f80fc62fdd7777d0d40a2e9dda0a05883ab11374334f6c4de38adffd \
- --hash=sha256:504b320cd4b7eff6f968eddf81127112db685e81f7e36e75f9f84f0df46041c3 \
- --hash=sha256:525808b8019e36eb524b8c68acdd63a37e75714eac50e988180b169d64480a00 \
- --hash=sha256:56d9f2ecac662ca1611d183feb03a3fa4406469dafe241673d521dd5ae92a155 \
- --hash=sha256:5bbe06f8eeafd38e5d0a4894ffec89378b6c6a625ff57e3028921f8ff59318ac \
- --hash=sha256:65c1a9bcdadc6c28eecee2c119465aebff8f7a584dd719facdd9e825ec61ab52 \
- --hash=sha256:68e78619a61ecf91e76aa3e6e8e33fc4894a2bebe93410754bd28fce0a8a4f9f \
- --hash=sha256:69c0f17e9f5a7afdf2cc9fb2d1ce6aabdb3bafb7f38017c0b77862bcec2bbad8 \
- --hash=sha256:6b2b56950d93e41f33b4223ead100ea0fe11f8e6ee5f641eb753ce4b77a7042b \
- --hash=sha256:715d3562f79d540f251b99ebd6d8baa547118974341db04f5ad06d5ea3eb8007 \
- --hash=sha256:787003c0ddb00500e49a10f2844fac87aa6ce977b90b0feaaf9de23c22508b24 \
- --hash=sha256:7ef3cb2ebbf91e330e3bb937efada0edd9003683db6b57bb108c4001f37a02ea \
- --hash=sha256:8023faf4e01efadfa183e863fefde0046de576c6f14659e8782065bcece22198 \
- --hash=sha256:8758846a7e80910096950b67071243da3e5a20ed2546e6392603c096778d48e0 \
- --hash=sha256:8afafd99945ead6e075b973fefa56379c5b5c53fd8937dad92c662da5d8fd5ee \
- --hash=sha256:8c41976a29d078bb235fea9b2ecd3da465df42a562910f9022f1a03107bd02be \
- --hash=sha256:8e254ae696c88d98da6555f5ace2279cf7cd5b3f52be2b5cf97feafe883b58d2 \
- --hash=sha256:8f9293864fe09b8149f0cc42ce56e3f0e54de883a9de90cd427f191c346eb2e1 \
- --hash=sha256:9402b03f1a1b4dc4c19845e5c749e3ab82d5078d16a2a4c2cd2df62d57bb0707 \
- --hash=sha256:962f82a3086483f5e5f64dbad880d31038b698494799b097bc59c2edf392fce6 \
- --hash=sha256:9aad3c1755095ce347e26488214ef77e0485a3c34a50c5a5e2471dff60b9dd9c \
- --hash=sha256:9dcdfd0eaf283af041973bff14a2e143b8bd64e069f4c383416ecd79a81aab58 \
- --hash=sha256:aa57bd9cf8ae831a362185ee444e15a93ecb2e344c8e52e4d721ea3ab6ef1823 \
- --hash=sha256:aa7bd130efab1c280bed0f45501b7c8795f9fdbeb02e965371bbef3523627779 \
- --hash=sha256:ab4a0df41e7c16a1392727727e7998a467472d0ad65f3ad5e6e765015df08636 \
- --hash=sha256:ad9e82fb8f09ade1c3e1b996a6337afac2b8b9e365f926f5a61aacc71adc5b3c \
- --hash=sha256:af598ed32d6ae86f1b747b82783958b1a4ab8f617b06fe68795c7f026abbdcad \
- --hash=sha256:b076b6226fb84157e3f7c971a47ff3a679d837cf338547532ab866c57930dbee \
- --hash=sha256:b7ff0f54cb4ff66dd38bebd335a38e2c22c41a8ee45aa608efc890ac3e3931bc \
- --hash=sha256:bfce63a9e7834b12b87c64d6b155fdd9b3b96191b6bd334bf37db7ff1fe457f2 \
- --hash=sha256:c011a4149cfbcf9f03994ec2edffcb8b1dc2d2aede7ca243746df97a5d41ce48 \
- --hash=sha256:c9c804664ebe8f83a211cace637506669e7890fec1b4195b505c214e50dd4eb7 \
- --hash=sha256:ca379055a47383d02a5400cb0d110cef0a776fc644cda797db0c5696cfd7e18e \
- --hash=sha256:cb0932dc158471523c9637e807d9bfb93e06a95cbf010f1a38b98623b929ef2b \
- --hash=sha256:cd0f502fe016460680cd20aaa5a76d241d6f35a1c3350c474bac1273803893fa \
- --hash=sha256:ceb01949af7121f9fc39f7d27f91be8546f3fb112c608bc4029aef0bab86a2a5 \
- --hash=sha256:d080e0a5eb2529460b30190fcfcc4199bd7f827663f858a226a81bc27beaa97e \
- --hash=sha256:dd15ff04ffd7e05ffcb7fe79f1b98041b8ea30ae9234aed2a9168b5797c3effb \
- --hash=sha256:df0be2b576a7abbf737b1575f048c23fb1d769f267ec4358296f31c2479db8f9 \
- --hash=sha256:e09031c87a1e51556fdcb46e5bd4f59dfb743061cf93c4d6831bf894f125eb57 \
- --hash=sha256:e4dd52d80b8c83fdce44e12478ad2e85c64ea965e75d66dbeafb0a3e77308fcc \
- --hash=sha256:f698de3fd0c4e6972b92290a45bd9b1536bffe8c6759c62471efaa8acb4c37bc \
- --hash=sha256:fec21693218efe39aa7f8599346e90c705afa52c5b31ae019b2e57e8f6542bb2 \
- --hash=sha256:ffcc3f7c66b5f5b7931a5aa68fc9cecc51e685ef90282f4a82f0f5e9b704ad11
+markupsafe==2.1.4 \
+ --hash=sha256:0042d6a9880b38e1dd9ff83146cc3c9c18a059b9360ceae207805567aacccc69 \
+ --hash=sha256:0c26f67b3fe27302d3a412b85ef696792c4a2386293c53ba683a89562f9399b0 \
+ --hash=sha256:0fbad3d346df8f9d72622ac71b69565e621ada2ce6572f37c2eae8dacd60385d \
+ --hash=sha256:15866d7f2dc60cfdde12ebb4e75e41be862348b4728300c36cdf405e258415ec \
+ --hash=sha256:1c98c33ffe20e9a489145d97070a435ea0679fddaabcafe19982fe9c971987d5 \
+ --hash=sha256:21e7af8091007bf4bebf4521184f4880a6acab8df0df52ef9e513d8e5db23411 \
+ --hash=sha256:23984d1bdae01bee794267424af55eef4dfc038dc5d1272860669b2aa025c9e3 \
+ --hash=sha256:31f57d64c336b8ccb1966d156932f3daa4fee74176b0fdc48ef580be774aae74 \
+ --hash=sha256:3583a3a3ab7958e354dc1d25be74aee6228938312ee875a22330c4dc2e41beb0 \
+ --hash=sha256:36d7626a8cca4d34216875aee5a1d3d654bb3dac201c1c003d182283e3205949 \
+ --hash=sha256:396549cea79e8ca4ba65525470d534e8a41070e6b3500ce2414921099cb73e8d \
+ --hash=sha256:3a66c36a3864df95e4f62f9167c734b3b1192cb0851b43d7cc08040c074c6279 \
+ --hash=sha256:3aae9af4cac263007fd6309c64c6ab4506dd2b79382d9d19a1994f9240b8db4f \
+ --hash=sha256:3ab3a886a237f6e9c9f4f7d272067e712cdb4efa774bef494dccad08f39d8ae6 \
+ --hash=sha256:47bb5f0142b8b64ed1399b6b60f700a580335c8e1c57f2f15587bd072012decc \
+ --hash=sha256:49a3b78a5af63ec10d8604180380c13dcd870aba7928c1fe04e881d5c792dc4e \
+ --hash=sha256:4df98d4a9cd6a88d6a585852f56f2155c9cdb6aec78361a19f938810aa020954 \
+ --hash=sha256:5045e892cfdaecc5b4c01822f353cf2c8feb88a6ec1c0adef2a2e705eef0f656 \
+ --hash=sha256:5244324676254697fe5c181fc762284e2c5fceeb1c4e3e7f6aca2b6f107e60dc \
+ --hash=sha256:54635102ba3cf5da26eb6f96c4b8c53af8a9c0d97b64bdcb592596a6255d8518 \
+ --hash=sha256:54a7e1380dfece8847c71bf7e33da5d084e9b889c75eca19100ef98027bd9f56 \
+ --hash=sha256:55d03fea4c4e9fd0ad75dc2e7e2b6757b80c152c032ea1d1de487461d8140efc \
+ --hash=sha256:698e84142f3f884114ea8cf83e7a67ca8f4ace8454e78fe960646c6c91c63bfa \
+ --hash=sha256:6aa5e2e7fc9bc042ae82d8b79d795b9a62bd8f15ba1e7594e3db243f158b5565 \
+ --hash=sha256:7653fa39578957bc42e5ebc15cf4361d9e0ee4b702d7d5ec96cdac860953c5b4 \
+ --hash=sha256:765f036a3d00395a326df2835d8f86b637dbaf9832f90f5d196c3b8a7a5080cb \
+ --hash=sha256:78bc995e004681246e85e28e068111a4c3f35f34e6c62da1471e844ee1446250 \
+ --hash=sha256:7a07f40ef8f0fbc5ef1000d0c78771f4d5ca03b4953fc162749772916b298fc4 \
+ --hash=sha256:8b570a1537367b52396e53325769608f2a687ec9a4363647af1cded8928af959 \
+ --hash=sha256:987d13fe1d23e12a66ca2073b8d2e2a75cec2ecb8eab43ff5624ba0ad42764bc \
+ --hash=sha256:9896fca4a8eb246defc8b2a7ac77ef7553b638e04fbf170bff78a40fa8a91474 \
+ --hash=sha256:9e9e3c4020aa2dc62d5dd6743a69e399ce3de58320522948af6140ac959ab863 \
+ --hash=sha256:a0b838c37ba596fcbfca71651a104a611543077156cb0a26fe0c475e1f152ee8 \
+ --hash=sha256:a4d176cfdfde84f732c4a53109b293d05883e952bbba68b857ae446fa3119b4f \
+ --hash=sha256:a76055d5cb1c23485d7ddae533229039b850db711c554a12ea64a0fd8a0129e2 \
+ --hash=sha256:a76cd37d229fc385738bd1ce4cba2a121cf26b53864c1772694ad0ad348e509e \
+ --hash=sha256:a7cc49ef48a3c7a0005a949f3c04f8baa5409d3f663a1b36f0eba9bfe2a0396e \
+ --hash=sha256:abf5ebbec056817057bfafc0445916bb688a255a5146f900445d081db08cbabb \
+ --hash=sha256:b0fe73bac2fed83839dbdbe6da84ae2a31c11cfc1c777a40dbd8ac8a6ed1560f \
+ --hash=sha256:b6f14a9cd50c3cb100eb94b3273131c80d102e19bb20253ac7bd7336118a673a \
+ --hash=sha256:b83041cda633871572f0d3c41dddd5582ad7d22f65a72eacd8d3d6d00291df26 \
+ --hash=sha256:b835aba863195269ea358cecc21b400276747cc977492319fd7682b8cd2c253d \
+ --hash=sha256:bf1196dcc239e608605b716e7b166eb5faf4bc192f8a44b81e85251e62584bd2 \
+ --hash=sha256:c669391319973e49a7c6230c218a1e3044710bc1ce4c8e6eb71f7e6d43a2c131 \
+ --hash=sha256:c7556bafeaa0a50e2fe7dc86e0382dea349ebcad8f010d5a7dc6ba568eaaa789 \
+ --hash=sha256:c8f253a84dbd2c63c19590fa86a032ef3d8cc18923b8049d91bcdeeb2581fbf6 \
+ --hash=sha256:d18b66fe626ac412d96c2ab536306c736c66cf2a31c243a45025156cc190dc8a \
+ --hash=sha256:d5291d98cd3ad9a562883468c690a2a238c4a6388ab3bd155b0c75dd55ece858 \
+ --hash=sha256:d5c31fe855c77cad679b302aabc42d724ed87c043b1432d457f4976add1c2c3e \
+ --hash=sha256:d6e427c7378c7f1b2bef6a344c925b8b63623d3321c09a237b7cc0e77dd98ceb \
+ --hash=sha256:dac1ebf6983148b45b5fa48593950f90ed6d1d26300604f321c74a9ca1609f8e \
+ --hash=sha256:de8153a7aae3835484ac168a9a9bdaa0c5eee4e0bc595503c95d53b942879c84 \
+ --hash=sha256:e1a0d1924a5013d4f294087e00024ad25668234569289650929ab871231668e7 \
+ --hash=sha256:e7902211afd0af05fbadcc9a312e4cf10f27b779cf1323e78d52377ae4b72bea \
+ --hash=sha256:e888ff76ceb39601c59e219f281466c6d7e66bd375b4ec1ce83bcdc68306796b \
+ --hash=sha256:f06e5a9e99b7df44640767842f414ed5d7bedaaa78cd817ce04bbd6fd86e2dd6 \
+ --hash=sha256:f6be2d708a9d0e9b0054856f07ac7070fbe1754be40ca8525d5adccdbda8f475 \
+ --hash=sha256:f9917691f410a2e0897d1ef99619fd3f7dd503647c8ff2475bf90c3cf222ad74 \
+ --hash=sha256:fc1a75aa8f11b87910ffd98de62b29d6520b6d6e8a3de69a70ca34dea85d2a8a \
+ --hash=sha256:fe8512ed897d5daf089e5bd010c3dc03bb1bdae00b35588c49b98268d4a01e00
# via
# jinja2
# werkzeug
diff --git a/src/ui/src/Instances.py b/src/ui/src/Instances.py
index 76fef8f0a..f1d062e9a 100644
--- a/src/ui/src/Instances.py
+++ b/src/ui/src/Instances.py
@@ -4,7 +4,7 @@ from os import sep
from os.path import join
from pathlib import Path
from subprocess import DEVNULL, STDOUT, run
-from typing import Any, Optional, Union
+from typing import Any, List, Optional, Tuple, Union
from API import API # type: ignore
from ApiCaller import ApiCaller # type: ignore
@@ -106,6 +106,18 @@ class Instance:
return self.apiCaller.send_to_apis("POST", "/restart")
+ def bans(self) -> Tuple[bool, dict[str, Any]]:
+ return self.apiCaller.send_to_apis("GET", "/bans", response=True)
+
+ def ban(self, ip: str, exp: float, reason: str) -> bool:
+ return self.apiCaller.send_to_apis("POST", "/ban", data={"ip": ip, "exp": exp, "reason": reason})
+
+ def unban(self, ip: str) -> bool:
+ return self.apiCaller.send_to_apis("POST", "/unban", data={"ip": ip})
+
+ def reports(self) -> Tuple[bool, dict[str, Any]]:
+ return self.apiCaller.send_to_apis("GET", "/metrics/requests", response=True)
+
class Instances:
def __init__(self, docker_client, kubernetes_client, integration: str):
@@ -214,10 +226,7 @@ class Instances:
)
)
- instances = sorted(
- instances,
- key=lambda x: x.name,
- )
+ instances.sort(key=lambda x: x.name)
# Local instance
if Path(sep, "usr", "sbin", "nginx").exists():
@@ -258,7 +267,7 @@ class Instances:
return not_reloaded or "Successfully reloaded instances"
def reload_instance(self, _id: Optional[int] = None, instance: Optional[Instance] = None) -> str:
- if instance is None:
+ if not instance:
instance = self.__instance_from_id(_id)
result = instance.reload()
@@ -297,3 +306,61 @@ class Instances:
return f"Instance {instance.name} has been restarted."
return f"Can't restart {instance.name}"
+
+ def get_bans(self, _id: Optional[int] = None) -> List[dict[str, Any]]:
+ if _id:
+ instance = self.__instance_from_id(_id)
+ resp, instance_bans = instance.bans()
+ if not resp:
+ return []
+ return instance_bans[instance.name if instance.name != "local" else "127.0.0.1"].get("data", [])
+
+ bans: List[dict[str, Any]] = []
+ for instance in self.get_instances():
+ resp, instance_bans = instance.bans()
+ if not resp:
+ continue
+ bans.extend(instance_bans[instance.name if instance.name != "local" else "127.0.0.1"].get("data", []))
+
+ bans.sort(key=lambda x: x["exp"])
+
+ unique_bans = {}
+
+ return [unique_bans.setdefault(item["ip"], item) for item in bans if item["ip"] not in unique_bans]
+
+ def ban(self, ip: str, exp: float, reason: str, _id: Optional[int] = None) -> Union[str, list[str]]:
+ if _id:
+ instance = self.__instance_from_id(_id)
+ if instance.ban(ip, exp, reason):
+ return ""
+ return f"Can't ban {ip} on {instance.name}"
+
+ return [instance.name for instance in self.get_instances() if not instance.ban(ip, exp, reason)]
+
+ def unban(self, ip: str, _id: Optional[int] = None) -> Union[str, list[str]]:
+ if _id:
+ instance = self.__instance_from_id(_id)
+ if instance.unban(ip):
+ return ""
+ return f"Can't unban {ip} on {instance.name}"
+
+ return [instance.name for instance in self.get_instances() if not instance.unban(ip)]
+
+ def get_reports(self, _id: Optional[int] = None) -> List[dict[str, Any]]:
+ if _id:
+ instance = self.__instance_from_id(_id)
+ resp, instance_reports = instance.reports()
+ if not resp:
+ return []
+ return instance_reports[instance.name if instance.name != "local" else "127.0.0.1"].get("msg", [])
+
+ reports: List[dict[str, Any]] = []
+ for instance in self.get_instances():
+ resp, instance_reports = instance.reports()
+ if not resp:
+ continue
+ reports.extend(instance_reports[instance.name if instance.name != "local" else "127.0.0.1"].get("msg", []))
+
+ reports.sort(key=lambda x: x["date"], reverse=True)
+
+ return reports
diff --git a/src/ui/static/css/dashboard.css b/src/ui/static/css/dashboard.css
index 621b45455..ccfcfdd0b 100644
--- a/src/ui/static/css/dashboard.css
+++ b/src/ui/static/css/dashboard.css
@@ -1 +1 @@
-/*! tailwindcss v3.3.2 | MIT License | https://tailwindcss.com*/*,:after,:before{box-sizing:border-box;border:0 solid #e9ecef}:after,:before{--tw-content:""}html{line-height:1.5;-webkit-text-size-adjust:100%;-moz-tab-size:4;-o-tab-size:4;tab-size:4;font-family:Open Sans;font-feature-settings:normal;font-variation-settings:normal}body{margin:0;line-height:inherit}hr{height:0;color:inherit;border-top-width:1px}abbr:where([title]){-webkit-text-decoration:underline dotted;text-decoration:underline dotted}h1,h2,h3,h4,h5,h6{font-size:inherit;font-weight:inherit}a{color:inherit;text-decoration:inherit}b,strong{font-weight:bolder}code,kbd,pre,samp{font-family:ui-monospace,SFMono-Regular,Menlo,Monaco,Consolas,Liberation Mono,Courier New,monospace;font-size:1em}small{font-size:80%}sub,sup{font-size:75%;line-height:0;position:relative;vertical-align:initial}sub{bottom:-.25em}sup{top:-.5em}table{text-indent:0;border-color:inherit;border-collapse:collapse}button,input,optgroup,select,textarea{font-family:inherit;font-size:100%;font-weight:inherit;line-height:inherit;color:inherit;margin:0;padding:0}button,select{text-transform:none}[type=button],[type=reset],[type=submit],button{-webkit-appearance:button;background-color:initial;background-image:none}:-moz-focusring{outline:auto}:-moz-ui-invalid{box-shadow:none}progress{vertical-align:initial}::-webkit-inner-spin-button,::-webkit-outer-spin-button{height:auto}[type=search]{-webkit-appearance:textfield;outline-offset:-2px}::-webkit-search-decoration{-webkit-appearance:none}::-webkit-file-upload-button{-webkit-appearance:button;font:inherit}summary{display:list-item}blockquote,dd,dl,figure,h1,h2,h3,h4,h5,h6,hr,p,pre{margin:0}fieldset{margin:0}fieldset,legend{padding:0}menu,ol,ul{list-style:none;margin:0;padding:0}textarea{resize:vertical}input::-moz-placeholder,textarea::-moz-placeholder{opacity:1;color:#ced4da}input::placeholder,textarea::placeholder{opacity:1;color:#ced4da}[role=button],button{cursor:pointer}:disabled{cursor:default}audio,canvas,embed,iframe,img,object,svg,video{display:block;vertical-align:middle}img,video{max-width:100%;height:auto}[hidden]{display:none}*,::backdrop,:after,:before{--tw-border-spacing-x:0;--tw-border-spacing-y:0;--tw-translate-x:0;--tw-translate-y:0;--tw-rotate:0;--tw-skew-x:0;--tw-skew-y:0;--tw-scale-x:1;--tw-scale-y:1;--tw-pan-x: ;--tw-pan-y: ;--tw-pinch-zoom: ;--tw-scroll-snap-strictness:proximity;--tw-gradient-from-position: ;--tw-gradient-via-position: ;--tw-gradient-to-position: ;--tw-ordinal: ;--tw-slashed-zero: ;--tw-numeric-figure: ;--tw-numeric-spacing: ;--tw-numeric-fraction: ;--tw-ring-inset: ;--tw-ring-offset-width:0px;--tw-ring-offset-color:#fff;--tw-ring-color:#5e72e480;--tw-ring-offset-shadow:0 0 #0000;--tw-ring-shadow:0 0 #0000;--tw-shadow:0 0 #0000;--tw-shadow-colored:0 0 #0000;--tw-blur: ;--tw-brightness: ;--tw-contrast: ;--tw-grayscale: ;--tw-hue-rotate: ;--tw-invert: ;--tw-saturate: ;--tw-sepia: ;--tw-drop-shadow: ;--tw-backdrop-blur: ;--tw-backdrop-brightness: ;--tw-backdrop-contrast: ;--tw-backdrop-grayscale: ;--tw-backdrop-hue-rotate: ;--tw-backdrop-invert: ;--tw-backdrop-opacity: ;--tw-backdrop-saturate: ;--tw-backdrop-sepia: }.\!container{width:100%!important;margin-right:auto!important;margin-left:auto!important;padding-right:1.5rem!important;padding-left:1.5rem!important}.container{width:100%;margin-right:auto;margin-left:auto;padding-right:1.5rem;padding-left:1.5rem}@media (min-width:340px){.\!container{max-width:340px!important}.container{max-width:340px}}@media (min-width:576px){.\!container{max-width:576px!important}.container{max-width:576px}}@media (min-width:768px){.\!container{max-width:768px!important}.container{max-width:768px}}@media (min-width:992px){.\!container{max-width:992px!important}.container{max-width:992px}}@media (min-width:1200px){.\!container{max-width:1200px!important}.container{max-width:1200px}}@media (min-width:1320px){.\!container{max-width:1320px!important}.container{max-width:1320px}}@media (min-width:1920px){.\!container{max-width:1920px!important}.container{max-width:1920px}}a{letter-spacing:-.025rem}hr{margin:1rem 0;border:0;opacity:.25}img{max-width:none}label{display:inline-block}p{line-height:1.625;font-weight:400;margin-bottom:1rem}small{font-size:.875em}svg{display:inline}table{border-collapse:inherit}h1,h2,h3,h4,h5,h6{margin-bottom:.5rem;color:#344767}h1,h2,h3,h4{letter-spacing:-.05rem}h1,h2,h3{font-weight:700}h4,h5,h6{font-weight:600}h1{font-size:3rem;line-height:1.25}h2{font-size:2.25rem;line-height:1.3}h3{font-size:1.875rem}h3,h4{line-height:1.375}h4{font-size:1.5rem}h5{font-size:1.25rem;line-height:1.375}h6{font-size:1rem;line-height:1.625}.sr-only{position:absolute;width:1px;height:1px;padding:0;margin:-1px;overflow:hidden;clip:rect(0,0,0,0);white-space:nowrap;border-width:0}.pointer-events-none{pointer-events:none}.visible{visibility:visible}.invisible{visibility:hidden}.collapse{visibility:collapse}.static{position:static}.fixed{position:fixed}.absolute{position:absolute}.relative{position:relative}.inset-y-0{top:0;bottom:0}.-left-full{left:-100%}.-right-0{right:0}.-right-1{right:-.25rem}.bottom-0{bottom:0}.left-0{left:0}.left-auto{left:auto}.left-full{left:100%}.right-0{right:0}.right-2{right:.5rem}.right-20{right:5rem}.right-4{right:1rem}.right-5{right:1.25rem}.right-6{right:1.5rem}.right-7{right:1.75rem}.right-8{right:2rem}.right-\[3\.25rem\]{right:3.25rem}.top-0{top:0}.top-1{top:.25rem}.top-1\.5{top:.375rem}.top-16{top:4rem}.top-2{top:.5rem}.top-4{top:1rem}.top-\[38\%\]{top:38%}.top-\[4\.5rem\]{top:4.5rem}.top-\[52\%\]{top:52%}.top-\[55\%\]{top:55%}.top-\[8\.2rem\]{top:8.2rem}.-z-10{z-index:-10}.z-10{z-index:10}.z-100{z-index:100}.z-110{z-index:110}.z-20{z-index:20}.z-990{z-index:990}.z-\[10000\]{z-index:10000}.z-\[1000\]{z-index:1000}.z-\[1001\]{z-index:1001}.z-\[20\]{z-index:20}.z-sticky{z-index:1020}.order-1{order:1}.order-2{order:2}.col-span-1{grid-column:span 1/span 1}.col-span-10{grid-column:span 10/span 10}.col-span-11{grid-column:span 11/span 11}.col-span-12{grid-column:span 12/span 12}.col-span-2{grid-column:span 2/span 2}.col-span-3{grid-column:span 3/span 3}.col-span-9{grid-column:span 9/span 9}.float-right{float:right}.float-left{float:left}.m-0{margin:0}.m-1{margin:.25rem}.m-2{margin:.5rem}.m-4{margin:1rem}.mx-0{margin-left:0;margin-right:0}.mx-0\.5{margin-left:.125rem;margin-right:.125rem}.mx-1{margin-left:.25rem;margin-right:.25rem}.mx-2{margin-left:.5rem;margin-right:.5rem}.mx-2\.5{margin-left:.625rem;margin-right:.625rem}.mx-4{margin-left:1rem;margin-right:1rem}.mx-auto{margin-left:auto;margin-right:auto}.my-0{margin-top:0;margin-bottom:0}.my-1{margin-top:.25rem;margin-bottom:.25rem}.my-2{margin-top:.5rem;margin-bottom:.5rem}.my-3{margin-top:.75rem;margin-bottom:.75rem}.my-4{margin-top:1rem;margin-bottom:1rem}.mb-0{margin-bottom:0}.mb-0\.5{margin-bottom:.125rem}.mb-1{margin-bottom:.25rem}.mb-2{margin-bottom:.5rem}.mb-3{margin-bottom:.75rem}.mb-4{margin-bottom:1rem}.mb-6{margin-bottom:1.5rem}.mb-7{margin-bottom:1.75rem}.mb-8{margin-bottom:2rem}.ml-0{margin-left:0}.ml-1{margin-left:.25rem}.ml-12{margin-left:3rem}.ml-2{margin-left:.5rem}.ml-3{margin-left:.75rem}.ml-4{margin-left:1rem}.ml-6{margin-left:1.5rem}.ml-auto{margin-left:auto}.mr-1{margin-right:.25rem}.mr-12{margin-right:3rem}.mr-2{margin-right:.5rem}.mr-3{margin-right:.75rem}.mr-4{margin-right:1rem}.mt-0{margin-top:0}.mt-0\.5{margin-top:.125rem}.mt-1{margin-top:.25rem}.mt-10{margin-top:2.5rem}.mt-12{margin-top:3rem}.mt-16{margin-top:4rem}.mt-2{margin-top:.5rem}.mt-3{margin-top:.75rem}.mt-4{margin-top:1rem}.mt-6{margin-top:1.5rem}.mt-8{margin-top:2rem}.mt-\[4\.5rem\]{margin-top:4.5rem}.block{display:block}.inline-block{display:inline-block}.inline{display:inline}.flex{display:flex}.table{display:table}.grid{display:grid}.hidden{display:none}.h-1\/3{height:33.333333%}.h-12{height:3rem}.h-14{height:3.5rem}.h-19{height:4.75rem}.h-3{height:.75rem}.h-4{height:1rem}.h-4\.5{height:1.125rem}.h-40{height:10rem}.h-48{height:12rem}.h-5{height:1.25rem}.h-5\.5{height:1.375rem}.h-6{height:1.5rem}.h-8{height:2rem}.h-\[2\.5rem\]{height:2.5rem}.h-\[3\.5rem\]{height:3.5rem}.h-\[4rem\]{height:4rem}.h-\[90vh\]{height:90vh}.h-full{height:100%}.h-px{height:1px}.h-screen{height:100vh}.h-sidenav{height:calc(100vh - 450px)}.max-h-100{max-height:25rem}.max-h-135{max-height:33.75rem}.max-h-30{max-height:7.5rem}.max-h-80{max-height:20rem}.max-h-90{max-height:22.5rem}.max-h-screen{max-height:100vh}.min-h-12{min-height:3rem}.min-h-20{min-height:5rem}.min-h-50-screen{min-height:50vh}.min-h-52{min-height:13rem}.min-h-6{min-height:1.5rem}.min-h-\[100px\]{min-height:100px}.min-h-\[350px\]{min-height:350px}.min-h-\[55vh\]{min-height:55vh}.min-h-\[75px\]{min-height:75px}.min-h-\[85vh\]{min-height:85vh}.min-h-screen{min-height:100vh}.w-1{width:.25rem}.w-10{width:2.5rem}.w-11\/12{width:91.666667%}.w-12{width:3rem}.w-28{width:7rem}.w-3{width:.75rem}.w-4{width:1rem}.w-4\.5{width:1.125rem}.w-40{width:10rem}.w-48{width:12rem}.w-5{width:1.25rem}.w-5\.5{width:1.375rem}.w-50{width:12.5rem}.w-6{width:1.5rem}.w-8{width:2rem}.w-80{width:20rem}.w-90{width:22.5rem}.w-\[2\.5rem\]{width:2.5rem}.w-auto{width:auto}.w-fit{width:-moz-fit-content;width:fit-content}.w-full{width:100%}.w-screen{width:100vw}.min-w-0{min-width:0}.min-w-\[900px\]{min-width:900px}.max-w-180{max-width:45rem}.max-w-40{max-width:10rem}.max-w-60{max-width:15rem}.max-w-64{max-width:16rem}.max-w-\[1920px\]{max-width:1920px}.max-w-\[300px\]{max-width:300px}.max-w-\[400px\]{max-width:400px}.max-w-\[550px\]{max-width:550px}.max-w-full{max-width:100%}.flex-auto{flex:1 1 auto}.grow{flex-grow:1}.basis-full{flex-basis:100%}.-translate-x-1{--tw-translate-x:-0.25rem}.-translate-x-1,.-translate-x-1\.5{transform:translate(var(--tw-translate-x),var(--tw-translate-y)) rotate(var(--tw-rotate)) skewX(var(--tw-skew-x)) skewY(var(--tw-skew-y)) scaleX(var(--tw-scale-x)) scaleY(var(--tw-scale-y))}.-translate-x-1\.5{--tw-translate-x:-0.375rem}.-translate-x-full{--tw-translate-x:-100%}.-translate-x-full,.-translate-y-0{transform:translate(var(--tw-translate-x),var(--tw-translate-y)) rotate(var(--tw-rotate)) skewX(var(--tw-skew-x)) skewY(var(--tw-skew-y)) scaleX(var(--tw-scale-x)) scaleY(var(--tw-scale-y))}.-translate-y-0{--tw-translate-y:-0px}.-translate-y-0\.4{--tw-translate-y:-0.1rem}.-translate-y-0\.4,.-translate-y-0\.5{transform:translate(var(--tw-translate-x),var(--tw-translate-y)) rotate(var(--tw-rotate)) skewX(var(--tw-skew-x)) skewY(var(--tw-skew-y)) scaleX(var(--tw-scale-x)) scaleY(var(--tw-scale-y))}.-translate-y-0\.5{--tw-translate-y:-0.125rem}.-translate-y-1{--tw-translate-y:-0.25rem}.-translate-y-1,.-translate-y-1\.5{transform:translate(var(--tw-translate-x),var(--tw-translate-y)) rotate(var(--tw-rotate)) skewX(var(--tw-skew-x)) skewY(var(--tw-skew-y)) scaleX(var(--tw-scale-x)) scaleY(var(--tw-scale-y))}.-translate-y-1\.5{--tw-translate-y:-0.375rem}.translate-x-0{--tw-translate-x:0px}.translate-x-0,.translate-x-0\.5{transform:translate(var(--tw-translate-x),var(--tw-translate-y)) rotate(var(--tw-rotate)) skewX(var(--tw-skew-x)) skewY(var(--tw-skew-y)) scaleX(var(--tw-scale-x)) scaleY(var(--tw-scale-y))}.translate-x-0\.5{--tw-translate-x:0.125rem}.translate-x-1{--tw-translate-x:0.25rem}.translate-x-1,.translate-x-2{transform:translate(var(--tw-translate-x),var(--tw-translate-y)) rotate(var(--tw-rotate)) skewX(var(--tw-skew-x)) skewY(var(--tw-skew-y)) scaleX(var(--tw-scale-x)) scaleY(var(--tw-scale-y))}.translate-x-2{--tw-translate-x:0.5rem}.translate-x-90{--tw-translate-x:22.5rem}.translate-x-90,.translate-y-0{transform:translate(var(--tw-translate-x),var(--tw-translate-y)) rotate(var(--tw-rotate)) skewX(var(--tw-skew-x)) skewY(var(--tw-skew-y)) scaleX(var(--tw-scale-x)) scaleY(var(--tw-scale-y))}.translate-y-0{--tw-translate-y:0px}.translate-y-0\.5{--tw-translate-y:0.125rem}.translate-y-0\.5,.translate-y-1{transform:translate(var(--tw-translate-x),var(--tw-translate-y)) rotate(var(--tw-rotate)) skewX(var(--tw-skew-x)) skewY(var(--tw-skew-y)) scaleX(var(--tw-scale-x)) scaleY(var(--tw-scale-y))}.translate-y-1{--tw-translate-y:0.25rem}.translate-y-16{--tw-translate-y:4rem}.translate-y-16,.translate-y-2{transform:translate(var(--tw-translate-x),var(--tw-translate-y)) rotate(var(--tw-rotate)) skewX(var(--tw-skew-x)) skewY(var(--tw-skew-y)) scaleX(var(--tw-scale-x)) scaleY(var(--tw-scale-y))}.translate-y-2{--tw-translate-y:0.5rem}.-rotate-12{--tw-rotate:-12deg}.-rotate-12,.rotate-12{transform:translate(var(--tw-translate-x),var(--tw-translate-y)) rotate(var(--tw-rotate)) skewX(var(--tw-skew-x)) skewY(var(--tw-skew-y)) scaleX(var(--tw-scale-x)) scaleY(var(--tw-scale-y))}.rotate-12{--tw-rotate:12deg}.rotate-180{--tw-rotate:180deg}.rotate-180,.scale-105{transform:translate(var(--tw-translate-x),var(--tw-translate-y)) rotate(var(--tw-rotate)) skewX(var(--tw-skew-x)) skewY(var(--tw-skew-y)) scaleX(var(--tw-scale-x)) scaleY(var(--tw-scale-y))}.scale-105{--tw-scale-x:1.05;--tw-scale-y:1.05}.scale-110{--tw-scale-x:1.1;--tw-scale-y:1.1}.scale-110,.scale-50{transform:translate(var(--tw-translate-x),var(--tw-translate-y)) rotate(var(--tw-rotate)) skewX(var(--tw-skew-x)) skewY(var(--tw-skew-y)) scaleX(var(--tw-scale-x)) scaleY(var(--tw-scale-y))}.scale-50{--tw-scale-x:.5;--tw-scale-y:.5}.scale-90{--tw-scale-x:.9;--tw-scale-y:.9}.scale-90,.transform{transform:translate(var(--tw-translate-x),var(--tw-translate-y)) rotate(var(--tw-rotate)) skewX(var(--tw-skew-x)) skewY(var(--tw-skew-y)) scaleX(var(--tw-scale-x)) scaleY(var(--tw-scale-y))}.cursor-pointer{cursor:pointer}.select-none{-webkit-user-select:none;-moz-user-select:none;user-select:none}.resize{resize:both}.list-none{list-style-type:none}.appearance-none{-webkit-appearance:none;-moz-appearance:none;appearance:none}.grid-cols-1{grid-template-columns:repeat(1,minmax(0,1fr))}.grid-cols-12{grid-template-columns:repeat(12,minmax(0,1fr))}.grid-cols-2{grid-template-columns:repeat(2,minmax(0,1fr))}.flex-col{flex-direction:column}.flex-wrap{flex-wrap:wrap}.items-start{align-items:flex-start}.items-end{align-items:flex-end}.items-center{align-items:center}.justify-start{justify-content:flex-start}.justify-end{justify-content:flex-end}.justify-center{justify-content:center}.justify-between{justify-content:space-between}.justify-items-center{justify-items:center}.gap-2{gap:.5rem}.gap-3{gap:.75rem}.gap-4{gap:1rem}.gap-8{gap:2rem}.gap-x-4{-moz-column-gap:1rem;column-gap:1rem}.gap-y-2{row-gap:.5rem}.gap-y-4{row-gap:1rem}.overflow-auto{overflow:auto}.overflow-hidden{overflow:hidden}.overflow-x-auto{overflow-x:auto}.overflow-y-auto{overflow-y:auto}.overflow-x-hidden{overflow-x:hidden}.whitespace-normal{white-space:normal}.whitespace-nowrap{white-space:nowrap}.break-words{overflow-wrap:break-word}.rounded,.rounded-1{border-radius:.25rem}.rounded-1\.4{border-radius:.35rem}.rounded-10{border-radius:2.5rem}.rounded-2xl{border-radius:1rem}.rounded-circle{border-radius:50%}.rounded-full{border-radius:9999px}.rounded-lg{border-radius:.5rem}.rounded-none{border-radius:0}.rounded-xl{border-radius:.75rem}.rounded-b{border-bottom-right-radius:.25rem;border-bottom-left-radius:.25rem}.rounded-b-lg{border-bottom-left-radius:.5rem}.rounded-b-lg,.rounded-r-lg{border-bottom-right-radius:.5rem}.rounded-r-lg{border-top-right-radius:.5rem}.rounded-t{border-top-left-radius:.25rem;border-top-right-radius:.25rem}.rounded-t-2xl{border-top-left-radius:1rem;border-top-right-radius:1rem}.rounded-t-lg{border-top-left-radius:.5rem;border-top-right-radius:.5rem}.border{border-width:1px}.border-0{border-width:0}.border-2{border-width:2px}.border-b{border-bottom-width:1px}.border-b-0{border-bottom-width:0}.border-l{border-left-width:1px}.border-r{border-right-width:1px}.border-t{border-top-width:1px}.border-solid{border-style:solid}.border-dashed{border-style:dashed}.border-gray-200{--tw-border-opacity:1;border-color:rgb(233 236 239/var(--tw-border-opacity))}.border-gray-300{--tw-border-opacity:1;border-color:rgb(210 214 218/var(--tw-border-opacity))}.border-gray-400{--tw-border-opacity:1;border-color:rgb(206 212 218/var(--tw-border-opacity))}.border-primary{--tw-border-opacity:1;border-color:rgb(11 85 119/var(--tw-border-opacity))}.bg-blue-500{--tw-bg-opacity:1;background-color:rgb(94 114 228/var(--tw-bg-opacity))}.bg-gray-100{--tw-bg-opacity:1;background-color:rgb(235 239 244/var(--tw-bg-opacity))}.bg-gray-200{--tw-bg-opacity:1;background-color:rgb(233 236 239/var(--tw-bg-opacity))}.bg-gray-300{--tw-bg-opacity:1;background-color:rgb(210 214 218/var(--tw-bg-opacity))}.bg-gray-50{--tw-bg-opacity:1;background-color:rgb(248 249 250/var(--tw-bg-opacity))}.bg-gray-600\/50{background-color:#6c757d80}.bg-green-500{--tw-bg-opacity:1;background-color:rgb(34 197 94/var(--tw-bg-opacity))}.bg-orange-500{--tw-bg-opacity:1;background-color:rgb(251 99 64/var(--tw-bg-opacity))}.bg-primary{--tw-bg-opacity:1;background-color:rgb(11 85 119/var(--tw-bg-opacity))}.bg-primary\/20{background-color:#0b557733}.bg-red-500{--tw-bg-opacity:1;background-color:rgb(245 57 57/var(--tw-bg-opacity))}.bg-secondary{--tw-bg-opacity:1;background-color:rgb(46 172 104/var(--tw-bg-opacity))}.bg-sky-500{--tw-bg-opacity:1;background-color:rgb(14 165 233/var(--tw-bg-opacity))}.bg-slate-800\/10{background-color:#3a416f1a}.bg-transparent{background-color:initial}.bg-white{--tw-bg-opacity:1;background-color:rgb(255 255 255/var(--tw-bg-opacity))}.bg-yellow-500{--tw-bg-opacity:1;background-color:rgb(251 177 64/var(--tw-bg-opacity))}.bg-gradient-to-r{background-image:linear-gradient(to right,var(--tw-gradient-stops))}.bg-gradient-to-tl{background-image:linear-gradient(to top left,var(--tw-gradient-stops))}.bg-none{background-image:none}.from-transparent{--tw-gradient-from:#0000 var(--tw-gradient-from-position);--tw-gradient-to:#0000 var(--tw-gradient-to-position);--tw-gradient-stops:var(--tw-gradient-from),var(--tw-gradient-to)}.via-black\/40{--tw-gradient-to:#0000 var(--tw-gradient-to-position);--tw-gradient-stops:var(--tw-gradient-from),#0006 var(--tw-gradient-via-position),var(--tw-gradient-to)}.to-transparent{--tw-gradient-to:#0000 var(--tw-gradient-to-position)}.bg-150{background-size:150%}.bg-contain{background-size:contain}.bg-clip-border{background-clip:initial}.bg-clip-padding{background-clip:padding-box}.bg-center{background-position:50%}.bg-left{background-position:0}.bg-x-25{background-position:25% 0}.bg-no-repeat{background-repeat:no-repeat}.fill-amber-500{fill:#f59e0b}.fill-blue-500{fill:#5e72e4}.fill-gray-500{fill:#adb5bd}.fill-gray-600{fill:#6c757d}.fill-green-500{fill:#22c55e}.fill-primary{fill:#0b5577}.fill-red-500{fill:#f53939}.fill-sky-500{fill:#0ea5e9}.fill-slate-800{fill:#3a416f}.fill-white{fill:#fff}.fill-yellow-500{fill:#fbb140}.stroke-blue-400{stroke:#60a5fa}.stroke-blue-500{stroke:#5e72e4}.stroke-emerald-600{stroke:#059669}.stroke-gray-100{stroke:#ebeff4}.stroke-gray-600{stroke:#6c757d}.stroke-gray-700{stroke:#495057}.stroke-green-700{stroke:#15803d}.stroke-orange-500{stroke:#fb6340}.stroke-pink-600{stroke:#db2777}.stroke-red-500{stroke:#f53939}.stroke-sky-500{stroke:#0ea5e9}.stroke-yellow-500{stroke:#fbb140}.stroke-0{stroke-width:0}.object-cover{-o-object-fit:cover;object-fit:cover}.p-0{padding:0}.p-1{padding:.25rem}.p-2{padding:.5rem}.p-3{padding:.75rem}.p-4{padding:1rem}.px-0{padding-left:0;padding-right:0}.px-0\.5{padding-left:.125rem;padding-right:.125rem}.px-1{padding-left:.25rem;padding-right:.25rem}.px-1\.5{padding-left:.375rem;padding-right:.375rem}.px-2{padding-left:.5rem;padding-right:.5rem}.px-3{padding-left:.75rem;padding-right:.75rem}.px-4{padding-left:1rem;padding-right:1rem}.px-6{padding-left:1.5rem;padding-right:1.5rem}.px-8{padding-left:2rem;padding-right:2rem}.py-1{padding-top:.25rem;padding-bottom:.25rem}.py-1\.5{padding-top:.375rem;padding-bottom:.375rem}.py-16{padding-top:4rem;padding-bottom:4rem}.py-2{padding-top:.5rem;padding-bottom:.5rem}.py-2\.5{padding-top:.625rem;padding-bottom:.625rem}.py-3{padding-top:.75rem;padding-bottom:.75rem}.py-4{padding-top:1rem;padding-bottom:1rem}.py-6{padding-top:1.5rem;padding-bottom:1.5rem}.pb-0{padding-bottom:0}.pb-16{padding-bottom:4rem}.pb-2{padding-bottom:.5rem}.pb-4{padding-bottom:1rem}.pb-8{padding-bottom:2rem}.pl-0{padding-left:0}.pl-2{padding-left:.5rem}.pl-3{padding-left:.75rem}.pl-4{padding-left:1rem}.pl-6{padding-left:1.5rem}.pr-0{padding-right:0}.pr-8{padding-right:2rem}.pt-1{padding-top:.25rem}.pt-10{padding-top:2.5rem}.pt-20{padding-top:5rem}.pt-3{padding-top:.75rem}.pt-4{padding-top:1rem}.text-left{text-align:left}.text-center{text-align:center}.align-top{vertical-align:top}.align-middle{vertical-align:middle}.align-bottom{vertical-align:bottom}.font-sans{font-family:Open Sans}.text-2xl{font-size:1.5rem;line-height:2rem}.text-3xl{font-size:1.875rem;line-height:2.25rem}.text-base{font-size:1rem;line-height:1.5rem}.text-lg{font-size:1.125rem;line-height:1.75rem}.text-sm{font-size:.875rem;line-height:1.5rem}.text-xl{font-size:1.25rem;line-height:1.75rem}.text-xs{font-size:.75rem;line-height:1rem}.font-bold{font-weight:700}.font-medium{font-weight:500}.font-normal{font-weight:400}.font-semibold{font-weight:600}.uppercase{text-transform:uppercase}.capitalize{text-transform:capitalize}.italic{font-style:italic}.ordinal{--tw-ordinal:ordinal;font-variant-numeric:var(--tw-ordinal) var(--tw-slashed-zero) var(--tw-numeric-figure) var(--tw-numeric-spacing) var(--tw-numeric-fraction)}.leading-5{line-height:1.25rem}.leading-5\.6{line-height:1.4rem}.leading-6{line-height:1.5rem}.leading-8{line-height:2rem}.leading-default{line-height:1.6}.leading-none{line-height:1}.leading-normal{line-height:1.5}.leading-tight{line-height:1.25}.tracking-normal{letter-spacing:0}.tracking-tight-rem{letter-spacing:-.025rem}.tracking-wide{letter-spacing:.025em}.tracking-widest{letter-spacing:.1em}.text-blue-500{--tw-text-opacity:1;color:rgb(94 114 228/var(--tw-text-opacity))}.text-emerald-500{--tw-text-opacity:1;color:rgb(45 206 137/var(--tw-text-opacity))}.text-gray-100{--tw-text-opacity:1;color:rgb(235 239 244/var(--tw-text-opacity))}.text-gray-300{--tw-text-opacity:1;color:rgb(210 214 218/var(--tw-text-opacity))}.text-gray-600{--tw-text-opacity:1;color:rgb(108 117 125/var(--tw-text-opacity))}.text-gray-600\/90{color:#6c757de6}.text-gray-700{--tw-text-opacity:1;color:rgb(73 80 87/var(--tw-text-opacity))}.text-gray-700\/80{color:#495057cc}.text-green-500{--tw-text-opacity:1;color:rgb(34 197 94/var(--tw-text-opacity))}.text-primary{--tw-text-opacity:1;color:rgb(11 85 119/var(--tw-text-opacity))}.text-red-500{--tw-text-opacity:1;color:rgb(245 57 57/var(--tw-text-opacity))}.text-sky-600{--tw-text-opacity:1;color:rgb(62 161 236/var(--tw-text-opacity))}.text-slate-500{--tw-text-opacity:1;color:rgb(103 116 142/var(--tw-text-opacity))}.text-slate-700{--tw-text-opacity:1;color:rgb(52 71 103/var(--tw-text-opacity))}.text-white{--tw-text-opacity:1;color:rgb(255 255 255/var(--tw-text-opacity))}.text-yellow-500{--tw-text-opacity:1;color:rgb(251 177 64/var(--tw-text-opacity))}.underline{text-decoration-line:underline}.antialiased{-webkit-font-smoothing:antialiased;-moz-osx-font-smoothing:grayscale}.opacity-0{opacity:0}.opacity-100{opacity:1}.opacity-50{opacity:.5}.opacity-60{opacity:.6}.shadow{--tw-shadow:0 1px 3px 0 #0000001a,0 1px 2px -1px #0000001a;--tw-shadow-colored:0 1px 3px 0 var(--tw-shadow-color),0 1px 2px -1px var(--tw-shadow-color)}.shadow,.shadow-3xl{box-shadow:var(--tw-ring-offset-shadow,0 0 #0000),var(--tw-ring-shadow,0 0 #0000),var(--tw-shadow)}.shadow-3xl{--tw-shadow:0 8px 26px -4px #14141426,0 8px 9px -5px #1414140f;--tw-shadow-colored:0 8px 26px -4px var(--tw-shadow-color),0 8px 9px -5px var(--tw-shadow-color)}.shadow-md{--tw-shadow:0 4px 6px #32325d1a,0 1px 3px #00000014;--tw-shadow-colored:0 4px 6px var(--tw-shadow-color),0 1px 3px var(--tw-shadow-color)}.shadow-md,.shadow-none{box-shadow:var(--tw-ring-offset-shadow,0 0 #0000),var(--tw-ring-shadow,0 0 #0000),var(--tw-shadow)}.shadow-none{--tw-shadow:0 0 #0000;--tw-shadow-colored:0 0 #0000}.shadow-sm{--tw-shadow:0 .25rem .375rem -.0625rem #1414141f,0 .125rem .25rem -.0625rem #14141412;--tw-shadow-colored:0 .25rem .375rem -.0625rem var(--tw-shadow-color),0 .125rem .25rem -.0625rem var(--tw-shadow-color)}.shadow-sm,.shadow-xl{box-shadow:var(--tw-ring-offset-shadow,0 0 #0000),var(--tw-ring-shadow,0 0 #0000),var(--tw-shadow)}.shadow-xl{--tw-shadow:0 0 2rem 0 #8898aa26;--tw-shadow-colored:0 0 2rem 0 var(--tw-shadow-color)}.shadow-xs{--tw-shadow:0 7px 14px #32325d1a,0 3px 6px #00000014;--tw-shadow-colored:0 7px 14px var(--tw-shadow-color),0 3px 6px var(--tw-shadow-color);box-shadow:var(--tw-ring-offset-shadow,0 0 #0000),var(--tw-ring-shadow,0 0 #0000),var(--tw-shadow)}.outline-none{outline:2px solid #0000;outline-offset:2px}.blur{--tw-blur:blur(8px)}.blur,.filter{filter:var(--tw-blur) var(--tw-brightness) var(--tw-contrast) var(--tw-grayscale) var(--tw-hue-rotate) var(--tw-invert) var(--tw-saturate) var(--tw-sepia) var(--tw-drop-shadow)}.transition{transition-property:color,background-color,border-color,text-decoration-color,fill,stroke,opacity,box-shadow,transform,filter,-webkit-backdrop-filter;transition-property:color,background-color,border-color,text-decoration-color,fill,stroke,opacity,box-shadow,transform,filter,backdrop-filter;transition-property:color,background-color,border-color,text-decoration-color,fill,stroke,opacity,box-shadow,transform,filter,backdrop-filter,-webkit-backdrop-filter;transition-timing-function:ease;transition-duration:.15s}.transition-all{transition-property:all;transition-timing-function:ease;transition-duration:.15s}.transition-transform{transition-property:transform;transition-timing-function:ease;transition-duration:.15s}.delay-200{transition-delay:.2s}.duration-200{transition-duration:.2s}.duration-250{transition-duration:.25s}.duration-300{transition-duration:.3s}.duration-700{transition-duration:.7s}.ease-in{transition-timing-function:ease-in}.ease-in-out{transition-timing-function:ease-in-out}.flex-wrap-inherit{flex-wrap:inherit}@font-face{font-family:Open Sans;src:url(../webfonts/OpenSans.ttf)}*{font-family:Open Sans,sans-serif!important}.ace_content,.ace_editor,.ace_editor div{font-family:Monaco,Menlo,Ubuntu Mono,Consolas,source-code-pro,monospace!important;font-size:16px!important;font-weight:400!important}.sr-only{display:none}.close-btn{display:inline-block;cursor:pointer;border-radius:.5rem;border-width:1px;--tw-border-opacity:1;border-color:rgb(245 57 57/var(--tw-border-opacity));--tw-bg-opacity:1;background-color:rgb(255 255 255/var(--tw-bg-opacity));padding:.75rem 1.5rem;text-align:center;vertical-align:middle;font-weight:700;text-transform:uppercase;line-height:1.5;letter-spacing:-.025rem;--tw-text-opacity:1;color:rgb(245 57 57/var(--tw-text-opacity));--tw-shadow:0 7px 14px #32325d1a,0 3px 6px #00000014;--tw-shadow-colored:0 7px 14px var(--tw-shadow-color),0 3px 6px var(--tw-shadow-color);transition-property:all;transition-timing-function:ease;transition-duration:.15s;transition-timing-function:ease-in}.close-btn,.close-btn:hover{box-shadow:var(--tw-ring-offset-shadow,0 0 #0000),var(--tw-ring-shadow,0 0 #0000),var(--tw-shadow)}.close-btn:hover{--tw-translate-y:-1px;transform:translate(var(--tw-translate-x),var(--tw-translate-y)) rotate(var(--tw-rotate)) skewX(var(--tw-skew-x)) skewY(var(--tw-skew-y)) scaleX(var(--tw-scale-x)) scaleY(var(--tw-scale-y));--tw-shadow:0 4px 6px #32325d1a,0 1px 3px #00000014;--tw-shadow-colored:0 4px 6px var(--tw-shadow-color),0 1px 3px var(--tw-shadow-color)}.close-btn:focus,.close-btn:hover{background-color:#fffc}.close-btn:active{opacity:.85}:is(.dark .close-btn){--tw-bg-opacity:1;background-color:rgb(233 236 239/var(--tw-bg-opacity));--tw-brightness:brightness(.9)}:is(.dark .close-btn),:is(.dark .close-btn:hover){filter:var(--tw-blur) var(--tw-brightness) var(--tw-contrast) var(--tw-grayscale) var(--tw-hue-rotate) var(--tw-invert) var(--tw-saturate) var(--tw-sepia) var(--tw-drop-shadow)}:is(.dark .close-btn:hover){--tw-brightness:brightness(.75)}.valid-btn{display:inline-block;cursor:pointer;border-radius:.5rem;--tw-bg-opacity:1;background-color:rgb(34 197 94/var(--tw-bg-opacity));padding:.75rem 1.5rem;text-align:center;vertical-align:middle;font-weight:700;text-transform:uppercase;line-height:1.5;letter-spacing:.025em;--tw-text-opacity:1;color:rgb(255 255 255/var(--tw-text-opacity));--tw-shadow:0 7px 14px #32325d1a,0 3px 6px #00000014;--tw-shadow-colored:0 7px 14px var(--tw-shadow-color),0 3px 6px var(--tw-shadow-color);transition-property:all;transition-timing-function:ease;transition-duration:.15s;transition-timing-function:ease-in}.valid-btn,.valid-btn:hover{box-shadow:var(--tw-ring-offset-shadow,0 0 #0000),var(--tw-ring-shadow,0 0 #0000),var(--tw-shadow)}.valid-btn:hover{--tw-translate-y:-1px;transform:translate(var(--tw-translate-x),var(--tw-translate-y)) rotate(var(--tw-rotate)) skewX(var(--tw-skew-x)) skewY(var(--tw-skew-y)) scaleX(var(--tw-scale-x)) scaleY(var(--tw-scale-y));--tw-shadow:0 4px 6px #32325d1a,0 1px 3px #00000014;--tw-shadow-colored:0 4px 6px var(--tw-shadow-color),0 1px 3px var(--tw-shadow-color)}.valid-btn:focus,.valid-btn:hover{background-color:#22c55ecc}.valid-btn:active{opacity:.85}:is(.dark .valid-btn){--tw-brightness:brightness(.9);filter:var(--tw-blur) var(--tw-brightness) var(--tw-contrast) var(--tw-grayscale) var(--tw-hue-rotate) var(--tw-invert) var(--tw-saturate) var(--tw-sepia) var(--tw-drop-shadow)}.delete-btn{display:inline-block;cursor:pointer;border-radius:.5rem;--tw-bg-opacity:1;background-color:rgb(245 57 57/var(--tw-bg-opacity));padding:.75rem 1.5rem;text-align:center;vertical-align:middle;font-weight:700;text-transform:uppercase;line-height:1.5;letter-spacing:.025em;--tw-text-opacity:1;color:rgb(255 255 255/var(--tw-text-opacity));--tw-shadow:0 7px 14px #32325d1a,0 3px 6px #00000014;--tw-shadow-colored:0 7px 14px var(--tw-shadow-color),0 3px 6px var(--tw-shadow-color);transition-property:all;transition-timing-function:ease;transition-duration:.15s;transition-timing-function:ease-in}.delete-btn,.delete-btn:hover{box-shadow:var(--tw-ring-offset-shadow,0 0 #0000),var(--tw-ring-shadow,0 0 #0000),var(--tw-shadow)}.delete-btn:hover{--tw-translate-y:-1px;transform:translate(var(--tw-translate-x),var(--tw-translate-y)) rotate(var(--tw-rotate)) skewX(var(--tw-skew-x)) skewY(var(--tw-skew-y)) scaleX(var(--tw-scale-x)) scaleY(var(--tw-scale-y));--tw-shadow:0 4px 6px #32325d1a,0 1px 3px #00000014;--tw-shadow-colored:0 4px 6px var(--tw-shadow-color),0 1px 3px var(--tw-shadow-color)}.delete-btn:focus,.delete-btn:hover{background-color:#f53939cc}.delete-btn:active{opacity:.85}:is(.dark .delete-btn){--tw-brightness:brightness(.9);filter:var(--tw-blur) var(--tw-brightness) var(--tw-contrast) var(--tw-grayscale) var(--tw-hue-rotate) var(--tw-invert) var(--tw-saturate) var(--tw-sepia) var(--tw-drop-shadow)}.edit-btn{display:inline-block;cursor:pointer;border-radius:.5rem;--tw-bg-opacity:1;background-color:rgb(251 177 64/var(--tw-bg-opacity));padding:.75rem 1.5rem;text-align:center;vertical-align:middle;font-weight:700;text-transform:uppercase;line-height:1.5;letter-spacing:.025em;--tw-text-opacity:1;color:rgb(255 255 255/var(--tw-text-opacity));--tw-shadow:0 7px 14px #32325d1a,0 3px 6px #00000014;--tw-shadow-colored:0 7px 14px var(--tw-shadow-color),0 3px 6px var(--tw-shadow-color);transition-property:all;transition-timing-function:ease;transition-duration:.15s;transition-timing-function:ease-in}.edit-btn,.edit-btn:hover{box-shadow:var(--tw-ring-offset-shadow,0 0 #0000),var(--tw-ring-shadow,0 0 #0000),var(--tw-shadow)}.edit-btn:hover{--tw-translate-y:-1px;transform:translate(var(--tw-translate-x),var(--tw-translate-y)) rotate(var(--tw-rotate)) skewX(var(--tw-skew-x)) skewY(var(--tw-skew-y)) scaleX(var(--tw-scale-x)) scaleY(var(--tw-scale-y));--tw-shadow:0 4px 6px #32325d1a,0 1px 3px #00000014;--tw-shadow-colored:0 4px 6px var(--tw-shadow-color),0 1px 3px var(--tw-shadow-color)}.edit-btn:focus,.edit-btn:hover{background-color:#fbb140cc}.edit-btn:active{opacity:.85}:is(.dark .edit-btn){--tw-brightness:brightness(.9);filter:var(--tw-blur) var(--tw-brightness) var(--tw-contrast) var(--tw-grayscale) var(--tw-hue-rotate) var(--tw-invert) var(--tw-saturate) var(--tw-sepia) var(--tw-drop-shadow)}.info-btn{display:inline-block;cursor:pointer;border-radius:.5rem;--tw-bg-opacity:1;background-color:rgb(14 165 233/var(--tw-bg-opacity));padding:.75rem 1.5rem;text-align:center;vertical-align:middle;font-weight:700;text-transform:uppercase;line-height:1.5;letter-spacing:.025em;--tw-text-opacity:1;color:rgb(255 255 255/var(--tw-text-opacity));--tw-shadow:0 7px 14px #32325d1a,0 3px 6px #00000014;--tw-shadow-colored:0 7px 14px var(--tw-shadow-color),0 3px 6px var(--tw-shadow-color);transition-property:all;transition-timing-function:ease;transition-duration:.15s;transition-timing-function:ease-in}.info-btn,.info-btn:hover{box-shadow:var(--tw-ring-offset-shadow,0 0 #0000),var(--tw-ring-shadow,0 0 #0000),var(--tw-shadow)}.info-btn:hover{--tw-translate-y:-1px;transform:translate(var(--tw-translate-x),var(--tw-translate-y)) rotate(var(--tw-rotate)) skewX(var(--tw-skew-x)) skewY(var(--tw-skew-y)) scaleX(var(--tw-scale-x)) scaleY(var(--tw-scale-y));--tw-shadow:0 4px 6px #32325d1a,0 1px 3px #00000014;--tw-shadow-colored:0 4px 6px var(--tw-shadow-color),0 1px 3px var(--tw-shadow-color)}.info-btn:focus,.info-btn:hover{background-color:#0ea5e9cc}.info-btn:active{opacity:.85}:is(.dark .info-btn){--tw-brightness:brightness(.9);filter:var(--tw-blur) var(--tw-brightness) var(--tw-contrast) var(--tw-grayscale) var(--tw-hue-rotate) var(--tw-invert) var(--tw-saturate) var(--tw-sepia) var(--tw-drop-shadow)}.checkbox{position:relative;z-index:10;float:left;margin-top:.25rem;height:1.25rem;width:1.25rem;cursor:pointer;-webkit-appearance:none;-moz-appearance:none;appearance:none;border-radius:.35rem;border-width:1px;border-color:rgb(210 214 218/var(--tw-border-opacity));background-color:rgb(255 255 255/var(--tw-bg-opacity));background-size:contain;background-position:50%;background-repeat:no-repeat;vertical-align:top;font-size:1rem;line-height:1.5rem;transition-property:all;transition-timing-function:ease;transition-duration:.25s}.checkbox,.checkbox:disabled{--tw-border-opacity:1;--tw-bg-opacity:1}.checkbox:disabled{cursor:default;border-color:rgb(206 212 218/var(--tw-border-opacity));background-color:rgb(206 212 218/var(--tw-bg-opacity));--tw-text-opacity:1;color:rgb(73 80 87/var(--tw-text-opacity))}.checkbox[data-checked=true]{z-index:0;--tw-border-opacity:1;border-color:rgb(11 85 119/var(--tw-border-opacity));--tw-bg-opacity:1;background-color:rgb(11 85 119/var(--tw-bg-opacity))}.checkbox:disabled[data-checked=true]{--tw-border-opacity:1;border-color:rgb(206 212 218/var(--tw-border-opacity));--tw-bg-opacity:1;background-color:rgb(206 212 218/var(--tw-bg-opacity));--tw-text-opacity:1;color:rgb(73 80 87/var(--tw-text-opacity))}:is(.dark .checkbox){--tw-border-opacity:1;border-color:rgb(98 117 148/var(--tw-border-opacity));--tw-bg-opacity:1;background-color:rgb(52 71 103/var(--tw-bg-opacity))}:is(.dark .checkbox:disabled){--tw-border-opacity:1;border-color:rgb(37 47 64/var(--tw-border-opacity));--tw-bg-opacity:1;background-color:rgb(37 47 64/var(--tw-bg-opacity));--tw-text-opacity:1;color:rgb(210 214 218/var(--tw-text-opacity))}:is(.dark .checkbox[data-checked=true]){--tw-border-opacity:1;border-color:rgb(11 85 119/var(--tw-border-opacity));--tw-bg-opacity:1;background-color:rgb(11 85 119/var(--tw-bg-opacity))}:is(.dark .checkbox:disabled[data-checked=true]){--tw-border-opacity:1;border-color:rgb(37 47 64/var(--tw-border-opacity));--tw-bg-opacity:1;background-color:rgb(37 47 64/var(--tw-bg-opacity));--tw-text-opacity:1;color:rgb(210 214 218/var(--tw-text-opacity))}.custom-select-btn{display:flex;width:100%;align-items:center;justify-content:space-between;border-radius:.5rem;border-width:1px;border-style:solid;--tw-border-opacity:1;border-color:rgb(210 214 218/var(--tw-border-opacity));--tw-bg-opacity:1;background-color:rgb(255 255 255/var(--tw-bg-opacity));background-clip:padding-box;padding:.25rem .375rem;text-align:left;vertical-align:middle;font-size:.875rem;font-weight:400;line-height:1.4rem;--tw-text-opacity:1;color:rgb(73 80 87/var(--tw-text-opacity));transition-property:all;transition-timing-function:ease;transition-duration:.3s;transition-timing-function:ease-in-out}.custom-select-btn::-moz-placeholder{--tw-text-opacity:1;color:rgb(173 181 189/var(--tw-text-opacity))}.custom-select-btn::placeholder{--tw-text-opacity:1;color:rgb(173 181 189/var(--tw-text-opacity))}.custom-select-btn:focus{--tw-border-opacity:1;border-color:rgb(11 85 119/var(--tw-border-opacity))}.custom-select-btn:disabled{--tw-border-opacity:1;border-color:rgb(206 212 218/var(--tw-border-opacity));--tw-bg-opacity:1;background-color:rgb(206 212 218/var(--tw-bg-opacity));--tw-text-opacity:1;color:rgb(73 80 87/var(--tw-text-opacity));opacity:.75}:is(.dark .custom-select-btn){border-color:rgb(98 117 148/var(--tw-border-opacity));background-color:rgb(52 71 103/var(--tw-bg-opacity));opacity:.9}:is(.dark .custom-select-btn),:is(.dark .custom-select-btn:disabled){--tw-border-opacity:1;--tw-bg-opacity:1;--tw-text-opacity:1;color:rgb(210 214 218/var(--tw-text-opacity))}:is(.dark .custom-select-btn:disabled){border-color:rgb(37 47 64/var(--tw-border-opacity));background-color:rgb(37 47 64/var(--tw-bg-opacity))}@media (min-width:768px){.custom-select-btn{padding:.5rem .75rem}}.custom-dropdown-btn{position:relative;margin-top:0;margin-bottom:0;min-height:38px;cursor:pointer;border-radius:0;border-bottom-width:1px;border-left-width:1px;border-right-width:1px;--tw-border-opacity:1;border-color:rgb(210 214 218/var(--tw-border-opacity));--tw-bg-opacity:1;background-color:rgb(255 255 255/var(--tw-bg-opacity));padding:.5rem 1.5rem;text-align:center;vertical-align:middle;font-size:.875rem;line-height:1.5rem;line-height:1.5;letter-spacing:-.025rem;--tw-text-opacity:1;color:rgb(73 80 87/var(--tw-text-opacity));transition-property:all;transition-timing-function:ease;transition-duration:.15s;transition-timing-function:ease-in}.custom-dropdown-btn:hover{--tw-brightness:brightness(.9);filter:var(--tw-blur) var(--tw-brightness) var(--tw-contrast) var(--tw-grayscale) var(--tw-hue-rotate) var(--tw-invert) var(--tw-saturate) var(--tw-sepia) var(--tw-drop-shadow)}:is(.dark .custom-dropdown-btn){border-color:rgb(98 117 148/var(--tw-border-opacity));background-color:rgb(52 71 103/var(--tw-bg-opacity))}.active.custom-dropdown-btn,:is(.dark .custom-dropdown-btn){--tw-border-opacity:1;--tw-bg-opacity:1;--tw-text-opacity:1;color:rgb(210 214 218/var(--tw-text-opacity))}.active.custom-dropdown-btn{position:relative;margin-top:0;margin-bottom:0;min-height:38px;cursor:pointer;border-radius:0;border-bottom-width:1px;border-left-width:1px;border-right-width:1px;border-color:rgb(210 214 218/var(--tw-border-opacity));background-color:rgb(11 85 119/var(--tw-bg-opacity));padding:.5rem 1.5rem;text-align:center;vertical-align:middle;font-size:.875rem;line-height:1.5rem;line-height:1.5;letter-spacing:-.025rem;transition-property:all;transition-timing-function:ease;transition-duration:.15s;transition-timing-function:ease-in}.active.custom-dropdown-btn:hover{--tw-brightness:brightness(.9);filter:var(--tw-blur) var(--tw-brightness) var(--tw-contrast) var(--tw-grayscale) var(--tw-hue-rotate) var(--tw-invert) var(--tw-saturate) var(--tw-sepia) var(--tw-drop-shadow)}:is(.dark .active.custom-dropdown-btn){border-color:rgb(98 117 148/var(--tw-border-opacity));background-color:rgb(11 85 119/var(--tw-bg-opacity));color:rgb(210 214 218/var(--tw-text-opacity))}.regular-input,:is(.dark .active.custom-dropdown-btn){--tw-border-opacity:1;--tw-bg-opacity:1;--tw-text-opacity:1}.regular-input{display:block;width:100%;-webkit-appearance:none;-moz-appearance:none;appearance:none;border-radius:.5rem;border-width:1px;border-style:solid;border-color:rgb(210 214 218/var(--tw-border-opacity));background-color:rgb(255 255 255/var(--tw-bg-opacity));background-clip:padding-box;padding:.25rem .375rem;font-size:.875rem;font-weight:400;line-height:1.4rem;color:rgb(73 80 87/var(--tw-text-opacity));outline:2px solid #0000;outline-offset:2px;transition-property:all;transition-timing-function:ease;transition-duration:.15s;transition-timing-function:ease-in}.regular-input::-moz-placeholder{--tw-text-opacity:1;color:rgb(173 181 189/var(--tw-text-opacity))}.regular-input::placeholder{--tw-text-opacity:1;color:rgb(173 181 189/var(--tw-text-opacity))}.regular-input:focus{border-color:#d2d6da00;--tw-ring-offset-shadow:var(--tw-ring-inset) 0 0 0 var(--tw-ring-offset-width) var(--tw-ring-offset-color);--tw-ring-shadow:var(--tw-ring-inset) 0 0 0 calc(1px + var(--tw-ring-offset-width)) var(--tw-ring-color);box-shadow:var(--tw-ring-offset-shadow),var(--tw-ring-shadow),var(--tw-shadow,0 0 #0000)}.regular-input:valid:focus{--tw-ring-opacity:1;--tw-ring-color:rgb(34 197 94/var(--tw-ring-opacity))}.regular-input:invalid:focus{--tw-ring-opacity:1;--tw-ring-color:rgb(245 57 57/var(--tw-ring-opacity))}.regular-input:disabled{--tw-bg-opacity:1;background-color:rgb(206 212 218/var(--tw-bg-opacity));--tw-text-opacity:1;color:rgb(73 80 87/var(--tw-text-opacity));opacity:.75}:is(.dark .regular-input){border-color:rgb(98 117 148/var(--tw-border-opacity));background-color:rgb(52 71 103/var(--tw-bg-opacity));opacity:.9}:is(.dark .regular-input),:is(.dark .regular-input:disabled){--tw-border-opacity:1;--tw-bg-opacity:1;--tw-text-opacity:1;color:rgb(210 214 218/var(--tw-text-opacity))}:is(.dark .regular-input:disabled){border-color:rgb(37 47 64/var(--tw-border-opacity));background-color:rgb(37 47 64/var(--tw-bg-opacity))}@media (min-width:768px){.regular-input{padding:.5rem .75rem}}.input-title{margin:0;font-size:.875rem;line-height:1.5rem;font-weight:700;transition-property:color,background-color,border-color,text-decoration-color,fill,stroke,opacity,box-shadow,transform,filter,-webkit-backdrop-filter;transition-property:color,background-color,border-color,text-decoration-color,fill,stroke,opacity,box-shadow,transform,filter,backdrop-filter;transition-property:color,background-color,border-color,text-decoration-color,fill,stroke,opacity,box-shadow,transform,filter,backdrop-filter,-webkit-backdrop-filter;transition-timing-function:ease;transition-duration:.3s;transition-timing-function:ease-in-out}:is(.dark .input-title){--tw-text-opacity:1;color:rgb(210 214 218/var(--tw-text-opacity));opacity:.9}.popover-settings-container{position:absolute;left:0;bottom:0;z-index:50;--tw-translate-y:-1.75rem;transform:translate(var(--tw-translate-x),var(--tw-translate-y)) rotate(var(--tw-rotate)) skewX(var(--tw-skew-x)) skewY(var(--tw-skew-y)) scaleX(var(--tw-scale-x)) scaleY(var(--tw-scale-y));border-radius:.375rem;--tw-bg-opacity:1;background-color:rgb(94 114 228/var(--tw-bg-opacity));padding:.75rem;transition-property:all;transition-property:color,background-color,border-color,text-decoration-color,fill,stroke,opacity,box-shadow,transform,filter,-webkit-backdrop-filter;transition-property:color,background-color,border-color,text-decoration-color,fill,stroke,opacity,box-shadow,transform,filter,backdrop-filter;transition-property:color,background-color,border-color,text-decoration-color,fill,stroke,opacity,box-shadow,transform,filter,backdrop-filter,-webkit-backdrop-filter;transition-timing-function:ease;transition-duration:.5s}:is(.dark .popover-settings-container){--tw-brightness:brightness(.9);filter:var(--tw-blur) var(--tw-brightness) var(--tw-contrast) var(--tw-grayscale) var(--tw-hue-rotate) var(--tw-invert) var(--tw-saturate) var(--tw-sepia) var(--tw-drop-shadow)}.popover-settings-text{margin:0;font-size:.875rem;line-height:1.5rem;font-weight:700;--tw-text-opacity:1;color:rgb(255 255 255/var(--tw-text-opacity));transition-property:color,background-color,border-color,text-decoration-color,fill,stroke,opacity,box-shadow,transform,filter,-webkit-backdrop-filter;transition-property:color,background-color,border-color,text-decoration-color,fill,stroke,opacity,box-shadow,transform,filter,backdrop-filter;transition-property:color,background-color,border-color,text-decoration-color,fill,stroke,opacity,box-shadow,transform,filter,backdrop-filter,-webkit-backdrop-filter;transition-timing-function:ease;transition-duration:.3s;transition-timing-function:ease-in-out}:is(.dark .popover-settings-text){--tw-text-opacity:1;color:rgb(235 239 244/var(--tw-text-opacity));opacity:.9}.popover-settings-svg{margin-left:.5rem;height:1.25rem;width:1.25rem;cursor:pointer;fill:#5e72e4}.popover-settings-svg:hover{--tw-brightness:brightness(.75);filter:var(--tw-blur) var(--tw-brightness) var(--tw-contrast) var(--tw-grayscale) var(--tw-hue-rotate) var(--tw-invert) var(--tw-saturate) var(--tw-sepia) var(--tw-drop-shadow)}.active.settings-tabs-tab-btn{position:relative;z-index:10;margin-top:.25rem;margin-bottom:.25rem;cursor:pointer;border-radius:0;border-width:1px;--tw-border-opacity:1;border-color:rgb(11 85 119/var(--tw-border-opacity));--tw-bg-opacity:1;background-color:rgb(255 255 255/var(--tw-bg-opacity));padding:.75rem;text-align:center;vertical-align:middle;font-size:.875rem;line-height:1.5rem;font-weight:700;text-transform:uppercase;line-height:1.5;letter-spacing:-.025rem;--tw-shadow:0 7px 14px #32325d1a,0 3px 6px #00000014;--tw-shadow-colored:0 7px 14px var(--tw-shadow-color),0 3px 6px var(--tw-shadow-color);box-shadow:var(--tw-ring-offset-shadow,0 0 #0000),var(--tw-ring-shadow,0 0 #0000),var(--tw-shadow);--tw-brightness:brightness(.9);filter:var(--tw-blur) var(--tw-brightness) var(--tw-contrast) var(--tw-grayscale) var(--tw-hue-rotate) var(--tw-invert) var(--tw-saturate) var(--tw-sepia) var(--tw-drop-shadow);transition-property:all;transition-timing-function:ease;transition-duration:.15s;transition-timing-function:ease-in}.active.settings-tabs-tab-btn:hover{--tw-bg-opacity:1;background-color:rgb(235 239 244/var(--tw-bg-opacity));--tw-shadow:0 4px 6px #32325d1a,0 1px 3px #00000014;--tw-shadow-colored:0 4px 6px var(--tw-shadow-color),0 1px 3px var(--tw-shadow-color);box-shadow:var(--tw-ring-offset-shadow,0 0 #0000),var(--tw-ring-shadow,0 0 #0000),var(--tw-shadow)}:is(.dark .active.settings-tabs-tab-btn){--tw-border-opacity:1;border-color:rgb(98 117 148/var(--tw-border-opacity));--tw-bg-opacity:1;background-color:rgb(52 71 103/var(--tw-bg-opacity))}:is(.dark .active.settings-tabs-tab-btn:hover){--tw-bg-opacity:1;background-color:rgb(58 65 111/var(--tw-bg-opacity))}.settings-tabs-tab-btn{position:relative;margin-top:.25rem;margin-bottom:.25rem;cursor:pointer;border-radius:0;border-width:1px;--tw-border-opacity:1;border-color:rgb(11 85 119/var(--tw-border-opacity));--tw-bg-opacity:1;background-color:rgb(255 255 255/var(--tw-bg-opacity));padding:.75rem;text-align:center;vertical-align:middle;font-size:.875rem;line-height:1.5rem;font-weight:700;text-transform:uppercase;line-height:1.5;letter-spacing:-.025rem;--tw-shadow:0 7px 14px #32325d1a,0 3px 6px #00000014;--tw-shadow-colored:0 7px 14px var(--tw-shadow-color),0 3px 6px var(--tw-shadow-color);box-shadow:var(--tw-ring-offset-shadow,0 0 #0000),var(--tw-ring-shadow,0 0 #0000),var(--tw-shadow);transition-property:all;transition-timing-function:ease;transition-duration:.15s;transition-timing-function:ease-in}.settings-tabs-tab-btn:hover{--tw-bg-opacity:1;background-color:rgb(235 239 244/var(--tw-bg-opacity));--tw-shadow:0 4px 6px #32325d1a,0 1px 3px #00000014;--tw-shadow-colored:0 4px 6px var(--tw-shadow-color),0 1px 3px var(--tw-shadow-color);box-shadow:var(--tw-ring-offset-shadow,0 0 #0000),var(--tw-ring-shadow,0 0 #0000),var(--tw-shadow)}:is(.dark .settings-tabs-tab-btn){--tw-border-opacity:1;border-color:rgb(98 117 148/var(--tw-border-opacity));--tw-bg-opacity:1;background-color:rgb(52 71 103/var(--tw-bg-opacity))}:is(.dark .settings-tabs-tab-btn:hover){--tw-bg-opacity:1;background-color:rgb(58 65 111/var(--tw-bg-opacity))}.settings-tabs-name{padding-left:.75rem;padding-right:.5rem;--tw-text-opacity:1;color:rgb(11 85 119/var(--tw-text-opacity));transition-property:color,background-color,border-color,text-decoration-color,fill,stroke,opacity,box-shadow,transform,filter,-webkit-backdrop-filter;transition-property:color,background-color,border-color,text-decoration-color,fill,stroke,opacity,box-shadow,transform,filter,backdrop-filter;transition-property:color,background-color,border-color,text-decoration-color,fill,stroke,opacity,box-shadow,transform,filter,backdrop-filter,-webkit-backdrop-filter;transition-timing-function:ease;transition-duration:.3s;transition-timing-function:ease-in-out}:is(.dark .settings-tabs-name){--tw-text-opacity:1;color:rgb(210 214 218/var(--tw-text-opacity));opacity:.9}.settings-tabs-popover-container{position:absolute;top:60px;left:0;z-index:50;min-width:150px;border-radius:.375rem;--tw-bg-opacity:1;background-color:rgb(94 114 228/var(--tw-bg-opacity));padding:.75rem;transition-property:color,background-color,border-color,text-decoration-color,fill,stroke,opacity,box-shadow,transform,filter,-webkit-backdrop-filter;transition-property:color,background-color,border-color,text-decoration-color,fill,stroke,opacity,box-shadow,transform,filter,backdrop-filter;transition-property:color,background-color,border-color,text-decoration-color,fill,stroke,opacity,box-shadow,transform,filter,backdrop-filter,-webkit-backdrop-filter;transition-timing-function:ease;transition-duration:.15s}:is(.dark .settings-tabs-popover-container){--tw-brightness:brightness(.9);filter:var(--tw-blur) var(--tw-brightness) var(--tw-contrast) var(--tw-grayscale) var(--tw-hue-rotate) var(--tw-invert) var(--tw-saturate) var(--tw-sepia) var(--tw-drop-shadow)}.settings-tabs-popover-text{margin:0;font-size:.875rem;line-height:1.5rem;font-weight:700;--tw-text-opacity:1;color:rgb(255 255 255/var(--tw-text-opacity))}.settings-tabs-mobile-btn{margin-top:.25rem;margin-bottom:.25rem;display:flex;width:100%;cursor:pointer;align-items:center;justify-content:space-between;border-radius:.5rem;border-width:1px;--tw-border-opacity:1;border-color:rgb(11 85 119/var(--tw-border-opacity));--tw-bg-opacity:1;background-color:rgb(255 255 255/var(--tw-bg-opacity));padding:.75rem 1.5rem;text-align:center;vertical-align:middle;font-size:.875rem;line-height:1.5rem;font-weight:700;text-transform:uppercase;line-height:1.5;letter-spacing:-.025rem;--tw-shadow:0 7px 14px #32325d1a,0 3px 6px #00000014;--tw-shadow-colored:0 7px 14px var(--tw-shadow-color),0 3px 6px var(--tw-shadow-color);box-shadow:var(--tw-ring-offset-shadow,0 0 #0000),var(--tw-ring-shadow,0 0 #0000),var(--tw-shadow);transition-property:all;transition-timing-function:ease;transition-duration:.15s;transition-timing-function:ease-in}.settings-tabs-mobile-btn:hover{--tw-translate-y:-1px;transform:translate(var(--tw-translate-x),var(--tw-translate-y)) rotate(var(--tw-rotate)) skewX(var(--tw-skew-x)) skewY(var(--tw-skew-y)) scaleX(var(--tw-scale-x)) scaleY(var(--tw-scale-y));--tw-bg-opacity:1;background-color:rgb(248 249 250/var(--tw-bg-opacity));--tw-shadow:0 4px 6px #32325d1a,0 1px 3px #00000014;--tw-shadow-colored:0 4px 6px var(--tw-shadow-color),0 1px 3px var(--tw-shadow-color);box-shadow:var(--tw-ring-offset-shadow,0 0 #0000),var(--tw-ring-shadow,0 0 #0000),var(--tw-shadow)}:is(.dark .settings-tabs-mobile-btn){--tw-border-opacity:1;border-color:rgb(98 117 148/var(--tw-border-opacity));--tw-bg-opacity:1;background-color:rgb(52 71 103/var(--tw-bg-opacity))}:is(.dark .settings-tabs-mobile-btn:hover){--tw-brightness:brightness(.95);filter:var(--tw-blur) var(--tw-brightness) var(--tw-contrast) var(--tw-grayscale) var(--tw-hue-rotate) var(--tw-invert) var(--tw-saturate) var(--tw-sepia) var(--tw-drop-shadow)}.settings-tabs-mobile-btn-text{--tw-text-opacity:1;color:rgb(11 85 119/var(--tw-text-opacity));transition-property:color,background-color,border-color,text-decoration-color,fill,stroke,opacity,box-shadow,transform,filter,-webkit-backdrop-filter;transition-property:color,background-color,border-color,text-decoration-color,fill,stroke,opacity,box-shadow,transform,filter,backdrop-filter;transition-property:color,background-color,border-color,text-decoration-color,fill,stroke,opacity,box-shadow,transform,filter,backdrop-filter,-webkit-backdrop-filter;transition-timing-function:ease;transition-duration:.3s;transition-timing-function:ease-in-out}:is(.dark .settings-tabs-mobile-btn-text){--tw-text-opacity:1;color:rgb(210 214 218/var(--tw-text-opacity));opacity:.9}.active.settings-tabs-mobile-dropdown-btn{position:relative;z-index:1000;margin-top:0;margin-bottom:0;cursor:pointer;border-radius:0;--tw-border-opacity:1;border-color:rgb(210 214 218/var(--tw-border-opacity));--tw-bg-opacity:1;background-color:rgb(11 85 119/var(--tw-bg-opacity));padding:.5rem 1.5rem;text-align:center;vertical-align:middle;font-size:.875rem;line-height:1.5rem;line-height:1.5;letter-spacing:-.025rem;--tw-text-opacity:1;color:rgb(210 214 218/var(--tw-text-opacity));transition-property:all;transition-timing-function:ease;transition-duration:.15s;transition-timing-function:ease-in}.active.settings-tabs-mobile-dropdown-btn:hover{--tw-brightness:brightness(.9);filter:var(--tw-blur) var(--tw-brightness) var(--tw-contrast) var(--tw-grayscale) var(--tw-hue-rotate) var(--tw-invert) var(--tw-saturate) var(--tw-sepia) var(--tw-drop-shadow)}:is(.dark .active.settings-tabs-mobile-dropdown-btn){--tw-border-opacity:1;border-color:rgb(98 117 148/var(--tw-border-opacity));--tw-bg-opacity:1;background-color:rgb(11 85 119/var(--tw-bg-opacity));--tw-text-opacity:1;color:rgb(210 214 218/var(--tw-text-opacity))}:is(.dark .active.settings-tabs-mobile-dropdown-btn:hover){--tw-brightness:brightness(.9);filter:var(--tw-blur) var(--tw-brightness) var(--tw-contrast) var(--tw-grayscale) var(--tw-hue-rotate) var(--tw-invert) var(--tw-saturate) var(--tw-sepia) var(--tw-drop-shadow)}.first.settings-tabs-mobile-dropdown-btn{border-top-left-radius:.25rem;border-top-right-radius:.25rem;border-width:1px}.settings-tabs-mobile-dropdown-btn{position:relative;margin-top:0;margin-bottom:0;display:flex;cursor:pointer;justify-content:space-between;border-radius:0;border-bottom-width:1px;border-left-width:1px;border-right-width:1px;--tw-border-opacity:1;border-color:rgb(210 214 218/var(--tw-border-opacity));--tw-bg-opacity:1;background-color:rgb(255 255 255/var(--tw-bg-opacity));padding:.5rem 1.5rem;text-align:center;vertical-align:middle;font-size:.875rem;line-height:1.5rem;line-height:1.5;letter-spacing:-.025rem;--tw-text-opacity:1;color:rgb(73 80 87/var(--tw-text-opacity));transition-property:all;transition-timing-function:ease;transition-duration:.15s;transition-timing-function:ease-in}.settings-tabs-mobile-dropdown-btn:hover{--tw-brightness:brightness(.9);filter:var(--tw-blur) var(--tw-brightness) var(--tw-contrast) var(--tw-grayscale) var(--tw-hue-rotate) var(--tw-invert) var(--tw-saturate) var(--tw-sepia) var(--tw-drop-shadow)}:is(.dark .settings-tabs-mobile-dropdown-btn){--tw-border-opacity:1;border-color:rgb(98 117 148/var(--tw-border-opacity));--tw-bg-opacity:1;background-color:rgb(52 71 103/var(--tw-bg-opacity));--tw-text-opacity:1;color:rgb(210 214 218/var(--tw-text-opacity))}:is(.dark .settings-tabs-mobile-dropdown-btn:hover){--tw-brightness:brightness(.9);filter:var(--tw-blur) var(--tw-brightness) var(--tw-contrast) var(--tw-grayscale) var(--tw-hue-rotate) var(--tw-invert) var(--tw-saturate) var(--tw-sepia) var(--tw-drop-shadow)}.first-letter\:absolute:first-letter{position:absolute}.first-letter\:w-full:first-letter{width:100%}.placeholder\:text-gray-500::-moz-placeholder{--tw-text-opacity:1;color:rgb(173 181 189/var(--tw-text-opacity))}.placeholder\:text-gray-500::placeholder{--tw-text-opacity:1;color:rgb(173 181 189/var(--tw-text-opacity))}.before\:float-left:before{content:var(--tw-content);float:left}.before\:pr-2:before{content:var(--tw-content);padding-right:.5rem}.before\:text-white:before{content:var(--tw-content);--tw-text-opacity:1;color:rgb(255 255 255/var(--tw-text-opacity))}.before\:content-\[\'\/\'\]:before{--tw-content:"/";content:var(--tw-content)}.after\:absolute:after{content:var(--tw-content);position:absolute}.after\:top-px:after{content:var(--tw-content);top:1px}.after\:float-right:after{content:var(--tw-content);float:right}.after\:h-4:after{content:var(--tw-content);height:1rem}.after\:w-4:after{content:var(--tw-content);width:1rem}.after\:translate-x-px:after{content:var(--tw-content);--tw-translate-x:1px;transform:translate(var(--tw-translate-x),var(--tw-translate-y)) rotate(var(--tw-rotate)) skewX(var(--tw-skew-x)) skewY(var(--tw-skew-y)) scaleX(var(--tw-scale-x)) scaleY(var(--tw-scale-y))}.after\:rounded-circle:after{content:var(--tw-content);border-radius:50%}.after\:bg-white:after{content:var(--tw-content);--tw-bg-opacity:1;background-color:rgb(255 255 255/var(--tw-bg-opacity))}.after\:pl-2:after{content:var(--tw-content);padding-left:.5rem}.after\:text-gray-600:after{content:var(--tw-content);--tw-text-opacity:1;color:rgb(108 117 125/var(--tw-text-opacity))}.after\:shadow-2xl:after{content:var(--tw-content);--tw-shadow:0 .3125rem .625rem 0 #0000001f;--tw-shadow-colored:0 .3125rem .625rem 0 var(--tw-shadow-color);box-shadow:var(--tw-ring-offset-shadow,0 0 #0000),var(--tw-ring-shadow,0 0 #0000),var(--tw-shadow)}.after\:duration-300:after{content:var(--tw-content);transition-duration:.3s}.after\:content-\[\'\'\]:after{--tw-content:"";content:var(--tw-content)}.after\:content-\[\'\/\'\]:after{--tw-content:"/";content:var(--tw-content)}.checked\:z-0:checked{z-index:0}.checked\:border-primary:checked{--tw-border-opacity:1;border-color:rgb(11 85 119/var(--tw-border-opacity))}.checked\:bg-primary:checked{--tw-bg-opacity:1;background-color:rgb(11 85 119/var(--tw-bg-opacity))}.checked\:bg-none:checked{background-image:none}.checked\:bg-right:checked{background-position:100%}.checked\:after\:translate-x-5:checked:after{--tw-translate-x:1.25rem}.checked\:after\:translate-x-5:checked:after,.checked\:after\:translate-x-5\.3:checked:after{content:var(--tw-content);transform:translate(var(--tw-translate-x),var(--tw-translate-y)) rotate(var(--tw-rotate)) skewX(var(--tw-skew-x)) skewY(var(--tw-skew-y)) scaleX(var(--tw-scale-x)) scaleY(var(--tw-scale-y))}.checked\:after\:translate-x-5\.3:checked:after{--tw-translate-x:1.3rem}.valid\:\!border-red-500:valid{--tw-border-opacity:1!important;border-color:rgb(245 57 57/var(--tw-border-opacity))!important}.hover\:-translate-y-0:hover{--tw-translate-y:-0px}.hover\:-translate-y-0:hover,.hover\:-translate-y-0\.4:hover{transform:translate(var(--tw-translate-x),var(--tw-translate-y)) rotate(var(--tw-rotate)) skewX(var(--tw-skew-x)) skewY(var(--tw-skew-y)) scaleX(var(--tw-scale-x)) scaleY(var(--tw-scale-y))}.hover\:-translate-y-0\.4:hover{--tw-translate-y:-0.1rem}.hover\:-translate-y-px:hover{--tw-translate-y:-1px}.hover\:-translate-y-px:hover,.hover\:scale-102:hover{transform:translate(var(--tw-translate-x),var(--tw-translate-y)) rotate(var(--tw-rotate)) skewX(var(--tw-skew-x)) skewY(var(--tw-skew-y)) scaleX(var(--tw-scale-x)) scaleY(var(--tw-scale-y))}.hover\:scale-102:hover{--tw-scale-x:1.02;--tw-scale-y:1.02}.hover\:rounded-lg:hover{border-radius:.5rem}.hover\:bg-gray-100:hover{--tw-bg-opacity:1;background-color:rgb(235 239 244/var(--tw-bg-opacity))}.hover\:bg-gray-300:hover{--tw-bg-opacity:1;background-color:rgb(210 214 218/var(--tw-bg-opacity))}.hover\:bg-green-500\/80:hover{background-color:#22c55ecc}.hover\:bg-primary\/30:hover{background-color:#0b55774d}.hover\:bg-primary\/5:hover{background-color:#0b55770d}.hover\:bg-primary\/80:hover{background-color:#0b5577cc}.hover\:bg-red-500\/80:hover{background-color:#f53939cc}.hover\:bg-sky-500\/80:hover{background-color:#0ea5e9cc}.hover\:bg-yellow-500\/80:hover{background-color:#fbb140cc}.hover\:italic:hover{font-style:italic}.hover\:no-underline:hover{text-decoration-line:none}.hover\:opacity-80:hover{opacity:.8}.hover\:shadow-md:hover{--tw-shadow:0 4px 6px #32325d1a,0 1px 3px #00000014;--tw-shadow-colored:0 4px 6px var(--tw-shadow-color),0 1px 3px var(--tw-shadow-color);box-shadow:var(--tw-ring-offset-shadow,0 0 #0000),var(--tw-ring-shadow,0 0 #0000),var(--tw-shadow)}.hover\:brightness-75:hover{--tw-brightness:brightness(.75)}.hover\:brightness-75:hover,.hover\:brightness-90:hover{filter:var(--tw-blur) var(--tw-brightness) var(--tw-contrast) var(--tw-grayscale) var(--tw-hue-rotate) var(--tw-invert) var(--tw-saturate) var(--tw-sepia) var(--tw-drop-shadow)}.hover\:brightness-90:hover{--tw-brightness:brightness(.9)}.hover\:brightness-95:hover{--tw-brightness:brightness(.95);filter:var(--tw-blur) var(--tw-brightness) var(--tw-contrast) var(--tw-grayscale) var(--tw-hue-rotate) var(--tw-invert) var(--tw-saturate) var(--tw-sepia) var(--tw-drop-shadow)}.focus\:\!border-red-500:focus{--tw-border-opacity:1!important;border-color:rgb(245 57 57/var(--tw-border-opacity))!important}.focus\:border-green-500:focus{--tw-border-opacity:1;border-color:rgb(34 197 94/var(--tw-border-opacity))}.focus\:border-primary:focus{--tw-border-opacity:1;border-color:rgb(11 85 119/var(--tw-border-opacity))}.focus\:bg-green-500\/80:focus{background-color:#22c55ecc}.focus\:bg-primary\/80:focus{background-color:#0b5577cc}.focus\:bg-red-500\/80:focus{background-color:#f53939cc}.focus\:bg-sky-500\/80:focus{background-color:#0ea5e9cc}.focus\:bg-yellow-500\/80:focus{background-color:#fbb140cc}.focus\:\!ring-red-500:focus{--tw-ring-opacity:1!important;--tw-ring-color:rgb(245 57 57/var(--tw-ring-opacity))!important}.focus\:valid\:\!border-red-500:valid:focus{--tw-border-opacity:1!important;border-color:rgb(245 57 57/var(--tw-border-opacity))!important}.focus\:valid\:border-green-500:valid:focus{--tw-border-opacity:1;border-color:rgb(34 197 94/var(--tw-border-opacity))}.focus\:valid\:\!ring-red-500:valid:focus{--tw-ring-opacity:1!important;--tw-ring-color:rgb(245 57 57/var(--tw-ring-opacity))!important}.focus\:invalid\:border-red-500:invalid:focus{--tw-border-opacity:1;border-color:rgb(245 57 57/var(--tw-border-opacity))}.focus\:file\:invalid\:border-red-500:invalid::file-selector-button:focus{--tw-border-opacity:1;border-color:rgb(245 57 57/var(--tw-border-opacity))}.active\:\!border-red-500:active{--tw-border-opacity:1!important;border-color:rgb(245 57 57/var(--tw-border-opacity))!important}.active\:opacity-85:active{opacity:.85}.active\:valid\:\!border-red-500:valid:active{--tw-border-opacity:1!important;border-color:rgb(245 57 57/var(--tw-border-opacity))!important}.disabled\:cursor-not-allowed:disabled{cursor:not-allowed}.disabled\:border-gray-400:disabled{--tw-border-opacity:1;border-color:rgb(206 212 218/var(--tw-border-opacity))}.disabled\:bg-gray-400:disabled{--tw-bg-opacity:1;background-color:rgb(206 212 218/var(--tw-bg-opacity))}.disabled\:text-gray-700:disabled{--tw-text-opacity:1;color:rgb(73 80 87/var(--tw-text-opacity))}.disabled\:opacity-75:disabled{opacity:.75}.disabled\:hover\:translate-y-0:hover:disabled{--tw-translate-y:0px;transform:translate(var(--tw-translate-x),var(--tw-translate-y)) rotate(var(--tw-rotate)) skewX(var(--tw-skew-x)) skewY(var(--tw-skew-y)) scaleX(var(--tw-scale-x)) scaleY(var(--tw-scale-y))}:is(.dark .dark\:inline){display:inline}:is(.dark .dark\:hidden){display:none}:is(.dark .dark\:border-gray-700){--tw-border-opacity:1;border-color:rgb(73 80 87/var(--tw-border-opacity))}:is(.dark .dark\:border-slate-600){--tw-border-opacity:1;border-color:rgb(98 117 148/var(--tw-border-opacity))}:is(.dark .dark\:border-slate-800){--tw-border-opacity:1;border-color:rgb(58 65 111/var(--tw-border-opacity))}:is(.dark .dark\:bg-gray-800){--tw-bg-opacity:1;background-color:rgb(37 47 64/var(--tw-bg-opacity))}:is(.dark .dark\:bg-green-500\/90){background-color:#22c55ee6}:is(.dark .dark\:bg-primary){--tw-bg-opacity:1;background-color:rgb(11 85 119/var(--tw-bg-opacity))}:is(.dark .dark\:bg-primary\/50){background-color:#0b557780}:is(.dark .dark\:bg-slate-700){--tw-bg-opacity:1;background-color:rgb(52 71 103/var(--tw-bg-opacity))}:is(.dark .dark\:bg-slate-700\/50){background-color:#34476780}:is(.dark .dark\:bg-slate-850){--tw-bg-opacity:1;background-color:rgb(17 28 68/var(--tw-bg-opacity))}:is(.dark .dark\:bg-slate-900){--tw-bg-opacity:1;background-color:rgb(5 17 57/var(--tw-bg-opacity))}:is(.dark .dark\:bg-slate-900\/30){background-color:#0511394d}:is(.dark .dark\:bg-gradient-to-r){background-image:linear-gradient(to right,var(--tw-gradient-stops))}:is(.dark .dark\:from-transparent){--tw-gradient-from:#0000 var(--tw-gradient-from-position);--tw-gradient-to:#0000 var(--tw-gradient-to-position);--tw-gradient-stops:var(--tw-gradient-from),var(--tw-gradient-to)}:is(.dark .dark\:via-white){--tw-gradient-to:#fff0 var(--tw-gradient-to-position);--tw-gradient-stops:var(--tw-gradient-from),#fff var(--tw-gradient-via-position),var(--tw-gradient-to)}:is(.dark .dark\:to-transparent){--tw-gradient-to:#0000 var(--tw-gradient-to-position)}:is(.dark .dark\:fill-blue-500){fill:#5e72e4}:is(.dark .dark\:fill-gray-300){fill:#d2d6da}:is(.dark .dark\:fill-gray-500){fill:#adb5bd}:is(.dark .dark\:fill-gray-600){fill:#6c757d}:is(.dark .dark\:stroke-gray-400){stroke:#ced4da}:is(.dark .dark\:stroke-gray-600){stroke:#6c757d}:is(.dark .dark\:text-gray-100){--tw-text-opacity:1;color:rgb(235 239 244/var(--tw-text-opacity))}:is(.dark .dark\:text-gray-200){--tw-text-opacity:1;color:rgb(233 236 239/var(--tw-text-opacity))}:is(.dark .dark\:text-gray-300){--tw-text-opacity:1;color:rgb(210 214 218/var(--tw-text-opacity))}:is(.dark .dark\:text-gray-400){--tw-text-opacity:1;color:rgb(206 212 218/var(--tw-text-opacity))}:is(.dark .dark\:text-gray-500){--tw-text-opacity:1;color:rgb(173 181 189/var(--tw-text-opacity))}:is(.dark .dark\:text-red-500){--tw-text-opacity:1;color:rgb(245 57 57/var(--tw-text-opacity))}:is(.dark .dark\:text-white){--tw-text-opacity:1;color:rgb(255 255 255/var(--tw-text-opacity))}:is(.dark .dark\:text-white\/80){color:#fffc}:is(.dark .dark\:text-white\/90){color:#ffffffe6}:is(.dark .dark\:opacity-60){opacity:.6}:is(.dark .dark\:opacity-75){opacity:.75}:is(.dark .dark\:opacity-80){opacity:.8}:is(.dark .dark\:opacity-90){opacity:.9}:is(.dark .dark\:shadow-dark-xl){--tw-shadow:0 2px 2px 0 #00000024,0 3px 1px -2px #0003,0 1px 5px 0 #0000001f;--tw-shadow-colored:0 2px 2px 0 var(--tw-shadow-color),0 3px 1px -2px var(--tw-shadow-color),0 1px 5px 0 var(--tw-shadow-color)}:is(.dark .dark\:shadow-dark-xl),:is(.dark .dark\:shadow-none){box-shadow:var(--tw-ring-offset-shadow,0 0 #0000),var(--tw-ring-shadow,0 0 #0000),var(--tw-shadow)}:is(.dark .dark\:shadow-none){--tw-shadow:0 0 #0000;--tw-shadow-colored:0 0 #0000}:is(.dark .dark\:brightness-110){--tw-brightness:brightness(1.1)}:is(.dark .dark\:brightness-110),:is(.dark .dark\:brightness-125){filter:var(--tw-blur) var(--tw-brightness) var(--tw-contrast) var(--tw-grayscale) var(--tw-hue-rotate) var(--tw-invert) var(--tw-saturate) var(--tw-sepia) var(--tw-drop-shadow)}:is(.dark .dark\:brightness-125){--tw-brightness:brightness(1.25)}:is(.dark .dark\:brightness-150){--tw-brightness:brightness(1.5)}:is(.dark .dark\:brightness-150),:is(.dark .dark\:brightness-90){filter:var(--tw-blur) var(--tw-brightness) var(--tw-contrast) var(--tw-grayscale) var(--tw-hue-rotate) var(--tw-invert) var(--tw-saturate) var(--tw-sepia) var(--tw-drop-shadow)}:is(.dark .dark\:brightness-90){--tw-brightness:brightness(.9)}:is(.dark .dark\:brightness-95){--tw-brightness:brightness(.95)}:is(.dark .dark\:brightness-95),:is(.dark .dark\:brightness-\[0\.885\]){filter:var(--tw-blur) var(--tw-brightness) var(--tw-contrast) var(--tw-grayscale) var(--tw-hue-rotate) var(--tw-invert) var(--tw-saturate) var(--tw-sepia) var(--tw-drop-shadow)}:is(.dark .dark\:brightness-\[0\.885\]){--tw-brightness:brightness(0.885)}:is(.dark .dark\:after\:text-gray-500):after{content:var(--tw-content);--tw-text-opacity:1;color:rgb(173 181 189/var(--tw-text-opacity))}:is(.dark .dark\:checked\:border-primary:checked){--tw-border-opacity:1;border-color:rgb(11 85 119/var(--tw-border-opacity))}:is(.dark .dark\:checked\:bg-primary:checked){--tw-bg-opacity:1;background-color:rgb(11 85 119/var(--tw-bg-opacity))}:is(.dark .dark\:hover\:bg-primary\/20:hover){background-color:#0b557733}:is(.dark .dark\:hover\:bg-primary\/60:hover){background-color:#0b557799}:is(.dark .dark\:hover\:bg-slate-700\/50:hover){background-color:#34476780}:is(.dark .dark\:hover\:bg-slate-800:hover){--tw-bg-opacity:1;background-color:rgb(58 65 111/var(--tw-bg-opacity))}:is(.dark .dark\:hover\:brightness-100:hover){--tw-brightness:brightness(1)}:is(.dark .dark\:hover\:brightness-100:hover),:is(.dark .dark\:hover\:brightness-105:hover){filter:var(--tw-blur) var(--tw-brightness) var(--tw-contrast) var(--tw-grayscale) var(--tw-hue-rotate) var(--tw-invert) var(--tw-saturate) var(--tw-sepia) var(--tw-drop-shadow)}:is(.dark .dark\:hover\:brightness-105:hover){--tw-brightness:brightness(1.05)}:is(.dark .dark\:hover\:brightness-90:hover){--tw-brightness:brightness(.9);filter:var(--tw-blur) var(--tw-brightness) var(--tw-contrast) var(--tw-grayscale) var(--tw-hue-rotate) var(--tw-invert) var(--tw-saturate) var(--tw-sepia) var(--tw-drop-shadow)}:is(.dark .dark\:disabled\:border-gray-800:disabled){--tw-border-opacity:1;border-color:rgb(37 47 64/var(--tw-border-opacity))}:is(.dark .dark\:disabled\:bg-gray-800:disabled){--tw-bg-opacity:1;background-color:rgb(37 47 64/var(--tw-bg-opacity))}:is(.dark .dark\:disabled\:text-gray-300:disabled){--tw-text-opacity:1;color:rgb(210 214 218/var(--tw-text-opacity))}@media (min-width:576px){.sm\:right-24{right:6rem}.sm\:right-40{right:10rem}.sm\:right-6{right:1.5rem}.sm\:top-2{top:.5rem}.sm\:top-\[4\.5rem\]{top:4.5rem}.sm\:col-span-4{grid-column:span 4/span 4}.sm\:col-span-6{grid-column:span 6/span 6}.sm\:col-start-5{grid-column-start:5}.sm\:mx-4{margin-left:1rem;margin-right:1rem}.sm\:mx-6{margin-left:1.5rem;margin-right:1.5rem}.sm\:ml-1{margin-left:.25rem}.sm\:mr-16{margin-right:4rem}.sm\:inline{display:inline}.sm\:h-10{height:2.5rem}.sm\:h-14{height:3.5rem}.sm\:h-7{height:1.75rem}.sm\:max-h-125{max-height:31.25rem}.sm\:max-h-28{max-height:7rem}.sm\:w-36{width:9rem}.sm\:w-50{width:12.5rem}.sm\:w-7{width:1.75rem}.sm\:min-w-\[500px\]{min-width:500px}.sm\:scale-100{--tw-scale-x:1;--tw-scale-y:1;transform:translate(var(--tw-translate-x),var(--tw-translate-y)) rotate(var(--tw-rotate)) skewX(var(--tw-skew-x)) skewY(var(--tw-skew-y)) scaleX(var(--tw-scale-x)) scaleY(var(--tw-scale-y))}.sm\:flex-row{flex-direction:row}.sm\:items-center{align-items:center}.sm\:justify-end{justify-content:flex-end}.sm\:justify-items-start{justify-items:start}.sm\:gap-4{gap:1rem}.sm\:px-12{padding-left:3rem;padding-right:3rem}.sm\:px-4{padding-left:1rem;padding-right:1rem}.sm\:px-6{padding-left:1.5rem;padding-right:1.5rem}.sm\:py-0{padding-top:0;padding-bottom:0}.sm\:pt-6{padding-top:1.5rem}.sm\:text-left{text-align:left}}@media (min-width:768px){.md\:right-8{right:2rem}.md\:right-\[3\.75rem\]{right:3.75rem}.md\:top-\[40\%\]{top:40%}.md\:col-span-4{grid-column:span 4/span 4}.md\:col-span-5{grid-column:span 5/span 5}.md\:col-span-6{grid-column:span 6/span 6}.md\:col-span-7{grid-column:span 7/span 7}.md\:col-span-8{grid-column:span 8/span 8}.md\:mx-6{margin-left:1.5rem;margin-right:1.5rem}.md\:my-3{margin-top:.75rem;margin-bottom:.75rem}.md\:mb-0{margin-bottom:0}.md\:mb-3{margin-bottom:.75rem}.md\:mb-8{margin-bottom:2rem}.md\:mr-3{margin-right:.75rem}.md\:mt-0{margin-top:0}.md\:mt-6{margin-top:1.5rem}.md\:block{display:block}.md\:hidden{display:none}.md\:h-16{height:4rem}.md\:max-h-160{max-height:40rem}.md\:min-h-75-screen{min-height:75vh}.md\:w-1\/2{width:50%}.md\:w-60{width:15rem}.md\:max-w-\[600px\]{max-width:600px}.md\:justify-end{justify-content:flex-end}.md\:gap-x-6{-moz-column-gap:1.5rem;column-gap:1.5rem}.md\:px-3{padding-left:.75rem;padding-right:.75rem}.md\:px-4{padding-left:1rem;padding-right:1rem}.md\:px-6{padding-left:1.5rem;padding-right:1.5rem}.md\:px-8{padding-left:2rem;padding-right:2rem}.md\:py-2{padding-top:.5rem;padding-bottom:.5rem}.md\:py-4{padding-top:1rem;padding-bottom:1rem}.md\:text-base{font-size:1rem;line-height:1.5rem}}@media (min-width:992px){.lg\:relative{position:relative}.lg\:order-1{order:1}.lg\:order-2{order:2}.lg\:col-span-1{grid-column:span 1/span 1}.lg\:col-span-4{grid-column:span 4/span 4}.lg\:col-span-6{grid-column:span 6/span 6}.lg\:col-span-8{grid-column:span 8/span 8}.lg\:mx-0{margin-left:0;margin-right:0}.lg\:mx-8{margin-left:2rem;margin-right:2rem}.lg\:my-3{margin-top:.75rem;margin-bottom:.75rem}.lg\:mt-0{margin-top:0}.lg\:mt-4{margin-top:1rem}.lg\:block{display:block}.lg\:flex{display:flex}.lg\:hidden{display:none}.lg\:h-24{height:6rem}.lg\:h-9{height:2.25rem}.lg\:w-80{width:20rem}.lg\:w-9{width:2.25rem}.lg\:flex-row{flex-direction:row}.lg\:flex-nowrap{flex-wrap:nowrap}.lg\:justify-start{justify-content:flex-start}.lg\:justify-end{justify-content:flex-end}.lg\:justify-between{justify-content:space-between}.lg\:gap-6{gap:1.5rem}.lg\:bg-gray-50{--tw-bg-opacity:1;background-color:rgb(248 249 250/var(--tw-bg-opacity))}.lg\:px-6{padding-left:1.5rem;padding-right:1.5rem}.lg\:pb-1{padding-bottom:.25rem}.lg\:text-left{text-align:left}}@media (min-width:1200px){.xl\:left-0{left:0}.xl\:right-24{right:6rem}.xl\:right-6{right:1.5rem}.xl\:ml-6{margin-left:1.5rem}.xl\:ml-68{margin-left:17rem}.xl\:hidden{display:none}.xl\:translate-x-0{--tw-translate-x:0px;transform:translate(var(--tw-translate-x),var(--tw-translate-y)) rotate(var(--tw-rotate)) skewX(var(--tw-skew-x)) skewY(var(--tw-skew-y)) scaleX(var(--tw-scale-x)) scaleY(var(--tw-scale-y))}.xl\:p-1{padding:.25rem}.xl\:p-1\.5{padding:.375rem}.xl\:pl-75{padding-left:18.75rem}.xl\:text-base{font-size:1rem;line-height:1.5rem}}@media (min-width:1320px){.\32xl\:col-span-4{grid-column:span 4/span 4}.\32xl\:col-span-6{grid-column:span 6/span 6}.\32xl\:mx-6{margin-left:1.5rem;margin-right:1.5rem}.\32xl\:my-3{margin-top:.75rem;margin-bottom:.75rem}}@media (min-width:1920px){.\33xl\:col-span-3{grid-column:span 3/span 3}.\33xl\:col-span-4{grid-column:span 4/span 4}.\33xl\:col-span-5{grid-column:span 5/span 5}}@media (min-width:340px){.xs\:flex-row{flex-direction:row}.xs\:items-center{align-items:center}.xs\:justify-start{justify-content:flex-start}.xs\:pl-2{padding-left:.5rem}.xs\:text-sm{font-size:.875rem;line-height:1.5rem}}.\[\&\>\*\]\:bg-primary>*{--tw-bg-opacity:1;background-color:rgb(11 85 119/var(--tw-bg-opacity))}
\ No newline at end of file
+/*! tailwindcss v3.3.2 | MIT License | https://tailwindcss.com*/*,:after,:before{box-sizing:border-box;border:0 solid #e9ecef}:after,:before{--tw-content:""}html{line-height:1.5;-webkit-text-size-adjust:100%;-moz-tab-size:4;-o-tab-size:4;tab-size:4;font-family:Open Sans;font-feature-settings:normal;font-variation-settings:normal}body{margin:0;line-height:inherit}hr{height:0;color:inherit;border-top-width:1px}abbr:where([title]){-webkit-text-decoration:underline dotted;text-decoration:underline dotted}h1,h2,h3,h4,h5,h6{font-size:inherit;font-weight:inherit}a{color:inherit;text-decoration:inherit}b,strong{font-weight:bolder}code,kbd,pre,samp{font-family:ui-monospace,SFMono-Regular,Menlo,Monaco,Consolas,Liberation Mono,Courier New,monospace;font-size:1em}small{font-size:80%}sub,sup{font-size:75%;line-height:0;position:relative;vertical-align:initial}sub{bottom:-.25em}sup{top:-.5em}table{text-indent:0;border-color:inherit;border-collapse:collapse}button,input,optgroup,select,textarea{font-family:inherit;font-size:100%;font-weight:inherit;line-height:inherit;color:inherit;margin:0;padding:0}button,select{text-transform:none}[type=button],[type=reset],[type=submit],button{-webkit-appearance:button;background-color:initial;background-image:none}:-moz-focusring{outline:auto}:-moz-ui-invalid{box-shadow:none}progress{vertical-align:initial}::-webkit-inner-spin-button,::-webkit-outer-spin-button{height:auto}[type=search]{-webkit-appearance:textfield;outline-offset:-2px}::-webkit-search-decoration{-webkit-appearance:none}::-webkit-file-upload-button{-webkit-appearance:button;font:inherit}summary{display:list-item}blockquote,dd,dl,figure,h1,h2,h3,h4,h5,h6,hr,p,pre{margin:0}fieldset{margin:0}fieldset,legend{padding:0}menu,ol,ul{list-style:none;margin:0;padding:0}textarea{resize:vertical}input::-moz-placeholder,textarea::-moz-placeholder{opacity:1;color:#ced4da}input::placeholder,textarea::placeholder{opacity:1;color:#ced4da}[role=button],button{cursor:pointer}:disabled{cursor:default}audio,canvas,embed,iframe,img,object,svg,video{display:block;vertical-align:middle}img,video{max-width:100%;height:auto}[hidden]{display:none}*,::backdrop,:after,:before{--tw-border-spacing-x:0;--tw-border-spacing-y:0;--tw-translate-x:0;--tw-translate-y:0;--tw-rotate:0;--tw-skew-x:0;--tw-skew-y:0;--tw-scale-x:1;--tw-scale-y:1;--tw-pan-x: ;--tw-pan-y: ;--tw-pinch-zoom: ;--tw-scroll-snap-strictness:proximity;--tw-gradient-from-position: ;--tw-gradient-via-position: ;--tw-gradient-to-position: ;--tw-ordinal: ;--tw-slashed-zero: ;--tw-numeric-figure: ;--tw-numeric-spacing: ;--tw-numeric-fraction: ;--tw-ring-inset: ;--tw-ring-offset-width:0px;--tw-ring-offset-color:#fff;--tw-ring-color:#5e72e480;--tw-ring-offset-shadow:0 0 #0000;--tw-ring-shadow:0 0 #0000;--tw-shadow:0 0 #0000;--tw-shadow-colored:0 0 #0000;--tw-blur: ;--tw-brightness: ;--tw-contrast: ;--tw-grayscale: ;--tw-hue-rotate: ;--tw-invert: ;--tw-saturate: ;--tw-sepia: ;--tw-drop-shadow: ;--tw-backdrop-blur: ;--tw-backdrop-brightness: ;--tw-backdrop-contrast: ;--tw-backdrop-grayscale: ;--tw-backdrop-hue-rotate: ;--tw-backdrop-invert: ;--tw-backdrop-opacity: ;--tw-backdrop-saturate: ;--tw-backdrop-sepia: }.\!container{width:100%!important;margin-right:auto!important;margin-left:auto!important;padding-right:1.5rem!important;padding-left:1.5rem!important}.container{width:100%;margin-right:auto;margin-left:auto;padding-right:1.5rem;padding-left:1.5rem}@media (min-width:340px){.\!container{max-width:340px!important}.container{max-width:340px}}@media (min-width:576px){.\!container{max-width:576px!important}.container{max-width:576px}}@media (min-width:768px){.\!container{max-width:768px!important}.container{max-width:768px}}@media (min-width:992px){.\!container{max-width:992px!important}.container{max-width:992px}}@media (min-width:1200px){.\!container{max-width:1200px!important}.container{max-width:1200px}}@media (min-width:1320px){.\!container{max-width:1320px!important}.container{max-width:1320px}}@media (min-width:1920px){.\!container{max-width:1920px!important}.container{max-width:1920px}}a{letter-spacing:-.025rem}hr{margin:1rem 0;border:0;opacity:.25}img{max-width:none}label{display:inline-block}p{line-height:1.625;font-weight:400;margin-bottom:1rem}small{font-size:.875em}svg{display:inline}table{border-collapse:inherit}h1,h2,h3,h4,h5,h6{margin-bottom:.5rem;color:#344767}h1,h2,h3,h4{letter-spacing:-.05rem}h1,h2,h3{font-weight:700}h4,h5,h6{font-weight:600}h1{font-size:3rem;line-height:1.25}h2{font-size:2.25rem;line-height:1.3}h3{font-size:1.875rem}h3,h4{line-height:1.375}h4{font-size:1.5rem}h5{font-size:1.25rem;line-height:1.375}h6{font-size:1rem;line-height:1.625}.sr-only{position:absolute;width:1px;height:1px;padding:0;margin:-1px;overflow:hidden;clip:rect(0,0,0,0);white-space:nowrap;border-width:0}.pointer-events-none{pointer-events:none}.visible{visibility:visible}.invisible{visibility:hidden}.collapse{visibility:collapse}.static{position:static}.fixed{position:fixed}.absolute{position:absolute}.relative{position:relative}.inset-y-0{top:0;bottom:0}.-left-full{left:-100%}.-right-0{right:0}.-right-1{right:-.25rem}.bottom-0{bottom:0}.left-0{left:0}.left-auto{left:auto}.left-full{left:100%}.right-0{right:0}.right-2{right:.5rem}.right-20{right:5rem}.right-4{right:1rem}.right-5{right:1.25rem}.right-6{right:1.5rem}.right-7{right:1.75rem}.right-8{right:2rem}.right-\[3\.25rem\]{right:3.25rem}.top-0{top:0}.top-1{top:.25rem}.top-1\.5{top:.375rem}.top-16{top:4rem}.top-2{top:.5rem}.top-4{top:1rem}.top-\[38\%\]{top:38%}.top-\[4\.5rem\]{top:4.5rem}.top-\[52\%\]{top:52%}.top-\[55\%\]{top:55%}.top-\[8\.2rem\]{top:8.2rem}.-z-10{z-index:-10}.z-10{z-index:10}.z-100{z-index:100}.z-110{z-index:110}.z-20{z-index:20}.z-990{z-index:990}.z-\[10000\]{z-index:10000}.z-\[1000\]{z-index:1000}.z-\[1001\]{z-index:1001}.z-\[20\]{z-index:20}.z-sticky{z-index:1020}.order-1{order:1}.order-2{order:2}.col-span-1{grid-column:span 1/span 1}.col-span-10{grid-column:span 10/span 10}.col-span-11{grid-column:span 11/span 11}.col-span-12{grid-column:span 12/span 12}.col-span-2{grid-column:span 2/span 2}.col-span-3{grid-column:span 3/span 3}.col-span-5{grid-column:span 5/span 5}.col-span-9{grid-column:span 9/span 9}.float-right{float:right}.float-left{float:left}.m-0{margin:0}.m-1{margin:.25rem}.m-2{margin:.5rem}.m-4{margin:1rem}.mx-0{margin-left:0;margin-right:0}.mx-0\.5{margin-left:.125rem;margin-right:.125rem}.mx-1{margin-left:.25rem;margin-right:.25rem}.mx-1\.5{margin-left:.375rem;margin-right:.375rem}.mx-2{margin-left:.5rem;margin-right:.5rem}.mx-2\.5{margin-left:.625rem;margin-right:.625rem}.mx-4{margin-left:1rem;margin-right:1rem}.mx-auto{margin-left:auto;margin-right:auto}.my-0{margin-top:0;margin-bottom:0}.my-1{margin-top:.25rem;margin-bottom:.25rem}.my-2{margin-top:.5rem;margin-bottom:.5rem}.my-3{margin-top:.75rem;margin-bottom:.75rem}.my-4{margin-top:1rem;margin-bottom:1rem}.mb-0{margin-bottom:0}.mb-0\.5{margin-bottom:.125rem}.mb-1{margin-bottom:.25rem}.mb-2{margin-bottom:.5rem}.mb-3{margin-bottom:.75rem}.mb-4{margin-bottom:1rem}.mb-6{margin-bottom:1.5rem}.mb-7{margin-bottom:1.75rem}.mb-8{margin-bottom:2rem}.ml-0{margin-left:0}.ml-1{margin-left:.25rem}.ml-12{margin-left:3rem}.ml-2{margin-left:.5rem}.ml-3{margin-left:.75rem}.ml-4{margin-left:1rem}.ml-auto{margin-left:auto}.mr-1{margin-right:.25rem}.mr-12{margin-right:3rem}.mr-2{margin-right:.5rem}.mr-3{margin-right:.75rem}.mr-4{margin-right:1rem}.mt-0{margin-top:0}.mt-0\.5{margin-top:.125rem}.mt-1{margin-top:.25rem}.mt-10{margin-top:2.5rem}.mt-12{margin-top:3rem}.mt-16{margin-top:4rem}.mt-2{margin-top:.5rem}.mt-3{margin-top:.75rem}.mt-4{margin-top:1rem}.mt-6{margin-top:1.5rem}.mt-8{margin-top:2rem}.mt-\[15vh\]{margin-top:15vh}.mt-\[4\.5rem\]{margin-top:4.5rem}.block{display:block}.inline-block{display:inline-block}.inline{display:inline}.flex{display:flex}.table{display:table}.grid{display:grid}.list-item{display:list-item}.hidden{display:none}.h-1\/3{height:33.333333%}.h-12{height:3rem}.h-14{height:3.5rem}.h-19{height:4.75rem}.h-3{height:.75rem}.h-4{height:1rem}.h-4\.5{height:1.125rem}.h-40{height:10rem}.h-48{height:12rem}.h-5{height:1.25rem}.h-5\.5{height:1.375rem}.h-6{height:1.5rem}.h-7{height:1.75rem}.h-8{height:2rem}.h-\[2\.5rem\]{height:2.5rem}.h-\[3\.5rem\]{height:3.5rem}.h-\[4rem\]{height:4rem}.h-\[90vh\]{height:90vh}.h-fit{height:-moz-fit-content;height:fit-content}.h-full{height:100%}.h-px{height:1px}.h-screen{height:100vh}.h-sidenav{height:calc(100vh - 450px)}.max-h-100{max-height:25rem}.max-h-135{max-height:33.75rem}.max-h-30{max-height:7.5rem}.max-h-80{max-height:20rem}.max-h-90{max-height:22.5rem}.max-h-\[250px\]{max-height:250px}.max-h-\[70vh\]{max-height:70vh}.max-h-\[90vh\]{max-height:90vh}.max-h-screen{max-height:100vh}.min-h-12{min-height:3rem}.min-h-20{min-height:5rem}.min-h-52{min-height:13rem}.min-h-6{min-height:1.5rem}.min-h-\[100px\]{min-height:100px}.min-h-\[350px\]{min-height:350px}.min-h-\[55vh\]{min-height:55vh}.min-h-\[75px\]{min-height:75px}.min-h-\[85vh\]{min-height:85vh}.min-h-screen{min-height:100vh}.w-1{width:.25rem}.w-10{width:2.5rem}.w-11\/12{width:91.666667%}.w-12{width:3rem}.w-28{width:7rem}.w-3{width:.75rem}.w-4{width:1rem}.w-4\.5{width:1.125rem}.w-40{width:10rem}.w-48{width:12rem}.w-5{width:1.25rem}.w-5\.5{width:1.375rem}.w-50{width:12.5rem}.w-6{width:1.5rem}.w-7{width:1.75rem}.w-8{width:2rem}.w-80{width:20rem}.w-90{width:22.5rem}.w-\[2\.5rem\]{width:2.5rem}.w-\[50vw\]{width:50vw}.w-auto{width:auto}.w-fit{width:-moz-fit-content;width:fit-content}.w-full{width:100%}.w-screen{width:100vw}.min-w-0{min-width:0}.min-w-\[1150px\]{min-width:1150px}.min-w-\[1200px\]{min-width:1200px}.min-w-\[600px\]{min-width:600px}.min-w-\[800px\]{min-width:800px}.min-w-\[900px\]{min-width:900px}.max-w-180{max-width:45rem}.max-w-40{max-width:10rem}.max-w-60{max-width:15rem}.max-w-64{max-width:16rem}.max-w-\[1920px\]{max-width:1920px}.max-w-\[300px\]{max-width:300px}.max-w-\[400px\]{max-width:400px}.max-w-\[550px\]{max-width:550px}.max-w-\[650px\]{max-width:650px}.max-w-\[700px\]{max-width:700px}.max-w-full{max-width:100%}.flex-auto{flex:1 1 auto}.grow{flex-grow:1}.basis-full{flex-basis:100%}.-translate-x-1{--tw-translate-x:-0.25rem}.-translate-x-1,.-translate-x-1\.5{transform:translate(var(--tw-translate-x),var(--tw-translate-y)) rotate(var(--tw-rotate)) skewX(var(--tw-skew-x)) skewY(var(--tw-skew-y)) scaleX(var(--tw-scale-x)) scaleY(var(--tw-scale-y))}.-translate-x-1\.5{--tw-translate-x:-0.375rem}.-translate-x-full{--tw-translate-x:-100%}.-translate-x-full,.-translate-y-0{transform:translate(var(--tw-translate-x),var(--tw-translate-y)) rotate(var(--tw-rotate)) skewX(var(--tw-skew-x)) skewY(var(--tw-skew-y)) scaleX(var(--tw-scale-x)) scaleY(var(--tw-scale-y))}.-translate-y-0{--tw-translate-y:-0px}.-translate-y-0\.4{--tw-translate-y:-0.1rem}.-translate-y-0\.4,.-translate-y-0\.5{transform:translate(var(--tw-translate-x),var(--tw-translate-y)) rotate(var(--tw-rotate)) skewX(var(--tw-skew-x)) skewY(var(--tw-skew-y)) scaleX(var(--tw-scale-x)) scaleY(var(--tw-scale-y))}.-translate-y-0\.5{--tw-translate-y:-0.125rem}.-translate-y-1{--tw-translate-y:-0.25rem}.-translate-y-1,.-translate-y-1\.5{transform:translate(var(--tw-translate-x),var(--tw-translate-y)) rotate(var(--tw-rotate)) skewX(var(--tw-skew-x)) skewY(var(--tw-skew-y)) scaleX(var(--tw-scale-x)) scaleY(var(--tw-scale-y))}.-translate-y-1\.5{--tw-translate-y:-0.375rem}.translate-x-0{--tw-translate-x:0px}.translate-x-0,.translate-x-0\.5{transform:translate(var(--tw-translate-x),var(--tw-translate-y)) rotate(var(--tw-rotate)) skewX(var(--tw-skew-x)) skewY(var(--tw-skew-y)) scaleX(var(--tw-scale-x)) scaleY(var(--tw-scale-y))}.translate-x-0\.5{--tw-translate-x:0.125rem}.translate-x-1{--tw-translate-x:0.25rem}.translate-x-1,.translate-x-2{transform:translate(var(--tw-translate-x),var(--tw-translate-y)) rotate(var(--tw-rotate)) skewX(var(--tw-skew-x)) skewY(var(--tw-skew-y)) scaleX(var(--tw-scale-x)) scaleY(var(--tw-scale-y))}.translate-x-2{--tw-translate-x:0.5rem}.translate-x-90{--tw-translate-x:22.5rem}.translate-x-90,.translate-y-0{transform:translate(var(--tw-translate-x),var(--tw-translate-y)) rotate(var(--tw-rotate)) skewX(var(--tw-skew-x)) skewY(var(--tw-skew-y)) scaleX(var(--tw-scale-x)) scaleY(var(--tw-scale-y))}.translate-y-0{--tw-translate-y:0px}.translate-y-0\.5{--tw-translate-y:0.125rem}.translate-y-0\.5,.translate-y-1{transform:translate(var(--tw-translate-x),var(--tw-translate-y)) rotate(var(--tw-rotate)) skewX(var(--tw-skew-x)) skewY(var(--tw-skew-y)) scaleX(var(--tw-scale-x)) scaleY(var(--tw-scale-y))}.translate-y-1{--tw-translate-y:0.25rem}.translate-y-16{--tw-translate-y:4rem}.translate-y-16,.translate-y-2{transform:translate(var(--tw-translate-x),var(--tw-translate-y)) rotate(var(--tw-rotate)) skewX(var(--tw-skew-x)) skewY(var(--tw-skew-y)) scaleX(var(--tw-scale-x)) scaleY(var(--tw-scale-y))}.translate-y-2{--tw-translate-y:0.5rem}.-rotate-12{--tw-rotate:-12deg}.-rotate-12,.rotate-12{transform:translate(var(--tw-translate-x),var(--tw-translate-y)) rotate(var(--tw-rotate)) skewX(var(--tw-skew-x)) skewY(var(--tw-skew-y)) scaleX(var(--tw-scale-x)) scaleY(var(--tw-scale-y))}.rotate-12{--tw-rotate:12deg}.rotate-180{--tw-rotate:180deg}.rotate-180,.scale-105{transform:translate(var(--tw-translate-x),var(--tw-translate-y)) rotate(var(--tw-rotate)) skewX(var(--tw-skew-x)) skewY(var(--tw-skew-y)) scaleX(var(--tw-scale-x)) scaleY(var(--tw-scale-y))}.scale-105{--tw-scale-x:1.05;--tw-scale-y:1.05}.scale-110{--tw-scale-x:1.1;--tw-scale-y:1.1}.scale-110,.scale-50{transform:translate(var(--tw-translate-x),var(--tw-translate-y)) rotate(var(--tw-rotate)) skewX(var(--tw-skew-x)) skewY(var(--tw-skew-y)) scaleX(var(--tw-scale-x)) scaleY(var(--tw-scale-y))}.scale-50{--tw-scale-x:.5;--tw-scale-y:.5}.scale-90{--tw-scale-x:.9;--tw-scale-y:.9}.scale-90,.transform{transform:translate(var(--tw-translate-x),var(--tw-translate-y)) rotate(var(--tw-rotate)) skewX(var(--tw-skew-x)) skewY(var(--tw-skew-y)) scaleX(var(--tw-scale-x)) scaleY(var(--tw-scale-y))}.cursor-pointer{cursor:pointer}.select-none{-webkit-user-select:none;-moz-user-select:none;user-select:none}.resize{resize:both}.list-none{list-style-type:none}.appearance-none{-webkit-appearance:none;-moz-appearance:none;appearance:none}.grid-cols-1{grid-template-columns:repeat(1,minmax(0,1fr))}.grid-cols-12{grid-template-columns:repeat(12,minmax(0,1fr))}.grid-cols-2{grid-template-columns:repeat(2,minmax(0,1fr))}.flex-col{flex-direction:column}.flex-wrap{flex-wrap:wrap}.items-start{align-items:flex-start}.items-end{align-items:flex-end}.items-center{align-items:center}.justify-start{justify-content:flex-start}.justify-end{justify-content:flex-end}.justify-center{justify-content:center}.justify-between{justify-content:space-between}.justify-items-center{justify-items:center}.gap-2{gap:.5rem}.gap-3{gap:.75rem}.gap-4{gap:1rem}.gap-8{gap:2rem}.gap-x-4{-moz-column-gap:1rem;column-gap:1rem}.gap-y-2{row-gap:.5rem}.gap-y-4{row-gap:1rem}.overflow-auto{overflow:auto}.overflow-hidden{overflow:hidden}.overflow-x-auto{overflow-x:auto}.overflow-y-auto{overflow-y:auto}.overflow-x-hidden{overflow-x:hidden}.whitespace-normal{white-space:normal}.whitespace-nowrap{white-space:nowrap}.break-words{overflow-wrap:break-word}.rounded,.rounded-1{border-radius:.25rem}.rounded-1\.4{border-radius:.35rem}.rounded-10{border-radius:2.5rem}.rounded-2xl{border-radius:1rem}.rounded-circle{border-radius:50%}.rounded-full{border-radius:9999px}.rounded-lg{border-radius:.5rem}.rounded-none{border-radius:0}.rounded-xl{border-radius:.75rem}.rounded-b{border-bottom-right-radius:.25rem;border-bottom-left-radius:.25rem}.rounded-b-lg{border-bottom-left-radius:.5rem}.rounded-b-lg,.rounded-r-lg{border-bottom-right-radius:.5rem}.rounded-r-lg{border-top-right-radius:.5rem}.rounded-t{border-top-left-radius:.25rem;border-top-right-radius:.25rem}.rounded-t-2xl{border-top-left-radius:1rem;border-top-right-radius:1rem}.rounded-t-lg{border-top-left-radius:.5rem;border-top-right-radius:.5rem}.border{border-width:1px}.border-0{border-width:0}.border-2{border-width:2px}.border-b{border-bottom-width:1px}.border-b-0{border-bottom-width:0}.border-l{border-left-width:1px}.border-r{border-right-width:1px}.border-t{border-top-width:1px}.border-solid{border-style:solid}.border-dashed{border-style:dashed}.border-gray-200{--tw-border-opacity:1;border-color:rgb(233 236 239/var(--tw-border-opacity))}.border-gray-300{--tw-border-opacity:1;border-color:rgb(210 214 218/var(--tw-border-opacity))}.border-gray-400{--tw-border-opacity:1;border-color:rgb(206 212 218/var(--tw-border-opacity))}.border-primary{--tw-border-opacity:1;border-color:rgb(11 85 119/var(--tw-border-opacity))}.bg-blue-500{--tw-bg-opacity:1;background-color:rgb(94 114 228/var(--tw-bg-opacity))}.bg-emerald-500{--tw-bg-opacity:1;background-color:rgb(45 206 137/var(--tw-bg-opacity))}.bg-gray-100{--tw-bg-opacity:1;background-color:rgb(235 239 244/var(--tw-bg-opacity))}.bg-gray-200{--tw-bg-opacity:1;background-color:rgb(233 236 239/var(--tw-bg-opacity))}.bg-gray-300{--tw-bg-opacity:1;background-color:rgb(210 214 218/var(--tw-bg-opacity))}.bg-gray-50{--tw-bg-opacity:1;background-color:rgb(248 249 250/var(--tw-bg-opacity))}.bg-gray-600\/50{background-color:#6c757d80}.bg-green-500{--tw-bg-opacity:1;background-color:rgb(34 197 94/var(--tw-bg-opacity))}.bg-orange-500{--tw-bg-opacity:1;background-color:rgb(251 99 64/var(--tw-bg-opacity))}.bg-primary{--tw-bg-opacity:1;background-color:rgb(11 85 119/var(--tw-bg-opacity))}.bg-primary\/20{background-color:#0b557733}.bg-red-500{--tw-bg-opacity:1;background-color:rgb(245 57 57/var(--tw-bg-opacity))}.bg-secondary{--tw-bg-opacity:1;background-color:rgb(46 172 104/var(--tw-bg-opacity))}.bg-sky-500{--tw-bg-opacity:1;background-color:rgb(14 165 233/var(--tw-bg-opacity))}.bg-slate-800\/10{background-color:#3a416f1a}.bg-transparent{background-color:initial}.bg-white{--tw-bg-opacity:1;background-color:rgb(255 255 255/var(--tw-bg-opacity))}.bg-yellow-500{--tw-bg-opacity:1;background-color:rgb(251 177 64/var(--tw-bg-opacity))}.bg-gradient-to-r{background-image:linear-gradient(to right,var(--tw-gradient-stops))}.bg-gradient-to-tl{background-image:linear-gradient(to top left,var(--tw-gradient-stops))}.bg-none{background-image:none}.from-transparent{--tw-gradient-from:#0000 var(--tw-gradient-from-position);--tw-gradient-to:#0000 var(--tw-gradient-to-position);--tw-gradient-stops:var(--tw-gradient-from),var(--tw-gradient-to)}.via-black\/40{--tw-gradient-to:#0000 var(--tw-gradient-to-position);--tw-gradient-stops:var(--tw-gradient-from),#0006 var(--tw-gradient-via-position),var(--tw-gradient-to)}.to-transparent{--tw-gradient-to:#0000 var(--tw-gradient-to-position)}.bg-150{background-size:150%}.bg-contain{background-size:contain}.bg-clip-border{background-clip:initial}.bg-clip-padding{background-clip:padding-box}.bg-center{background-position:50%}.bg-left{background-position:0}.bg-x-25{background-position:25% 0}.bg-no-repeat{background-repeat:no-repeat}.fill-amber-500{fill:#f59e0b}.fill-blue-500{fill:#5e72e4}.fill-gray-500{fill:#adb5bd}.fill-gray-600{fill:#6c757d}.fill-green-500{fill:#22c55e}.fill-primary{fill:#0b5577}.fill-red-500{fill:#f53939}.fill-sky-500{fill:#0ea5e9}.fill-slate-800{fill:#3a416f}.fill-white{fill:#fff}.fill-yellow-500{fill:#fbb140}.stroke-amber-500{stroke:#f59e0b}.stroke-blue-400{stroke:#60a5fa}.stroke-blue-500{stroke:#5e72e4}.stroke-emerald-600{stroke:#059669}.stroke-gray-100{stroke:#ebeff4}.stroke-gray-600{stroke:#6c757d}.stroke-gray-700{stroke:#495057}.stroke-green-700{stroke:#15803d}.stroke-orange-500{stroke:#fb6340}.stroke-pink-600{stroke:#db2777}.stroke-red-500{stroke:#f53939}.stroke-sky-500{stroke:#0ea5e9}.stroke-stone-500{stroke:#78716c}.stroke-white{stroke:#fff}.stroke-yellow-500{stroke:#fbb140}.stroke-0{stroke-width:0}.object-cover{-o-object-fit:cover;object-fit:cover}.p-0{padding:0}.p-1{padding:.25rem}.p-2{padding:.5rem}.p-3{padding:.75rem}.p-4{padding:1rem}.px-0{padding-left:0;padding-right:0}.px-0\.5{padding-left:.125rem;padding-right:.125rem}.px-1{padding-left:.25rem;padding-right:.25rem}.px-1\.5{padding-left:.375rem;padding-right:.375rem}.px-2{padding-left:.5rem;padding-right:.5rem}.px-3{padding-left:.75rem;padding-right:.75rem}.px-4{padding-left:1rem;padding-right:1rem}.px-6{padding-left:1.5rem;padding-right:1.5rem}.px-8{padding-left:2rem;padding-right:2rem}.py-1{padding-top:.25rem;padding-bottom:.25rem}.py-1\.5{padding-top:.375rem;padding-bottom:.375rem}.py-16{padding-top:4rem;padding-bottom:4rem}.py-2{padding-top:.5rem;padding-bottom:.5rem}.py-2\.5{padding-top:.625rem;padding-bottom:.625rem}.py-3{padding-top:.75rem;padding-bottom:.75rem}.py-4{padding-top:1rem;padding-bottom:1rem}.py-6{padding-top:1.5rem;padding-bottom:1.5rem}.pb-0{padding-bottom:0}.pb-16{padding-bottom:4rem}.pb-2{padding-bottom:.5rem}.pb-4{padding-bottom:1rem}.pb-8{padding-bottom:2rem}.pl-0{padding-left:0}.pl-2{padding-left:.5rem}.pl-3{padding-left:.75rem}.pl-4{padding-left:1rem}.pl-6{padding-left:1.5rem}.pr-0{padding-right:0}.pr-8{padding-right:2rem}.pt-1{padding-top:.25rem}.pt-10{padding-top:2.5rem}.pt-20{padding-top:5rem}.pt-3{padding-top:.75rem}.pt-4{padding-top:1rem}.text-left{text-align:left}.text-center{text-align:center}.align-top{vertical-align:top}.align-middle{vertical-align:middle}.align-bottom{vertical-align:bottom}.font-sans{font-family:Open Sans}.text-2xl{font-size:1.5rem;line-height:2rem}.text-3xl{font-size:1.875rem;line-height:2.25rem}.text-base{font-size:1rem;line-height:1.5rem}.text-lg{font-size:1.125rem;line-height:1.75rem}.text-sm{font-size:.875rem;line-height:1.5rem}.text-xl{font-size:1.25rem;line-height:1.75rem}.text-xs{font-size:.75rem;line-height:1rem}.font-bold{font-weight:700}.font-medium{font-weight:500}.font-normal{font-weight:400}.font-semibold{font-weight:600}.uppercase{text-transform:uppercase}.capitalize{text-transform:capitalize}.italic{font-style:italic}.ordinal{--tw-ordinal:ordinal;font-variant-numeric:var(--tw-ordinal) var(--tw-slashed-zero) var(--tw-numeric-figure) var(--tw-numeric-spacing) var(--tw-numeric-fraction)}.leading-5{line-height:1.25rem}.leading-5\.6{line-height:1.4rem}.leading-6{line-height:1.5rem}.leading-8{line-height:2rem}.leading-default{line-height:1.6}.leading-none{line-height:1}.leading-normal{line-height:1.5}.leading-tight{line-height:1.25}.tracking-normal{letter-spacing:0}.tracking-tight-rem{letter-spacing:-.025rem}.tracking-wide{letter-spacing:.025em}.tracking-widest{letter-spacing:.1em}.text-blue-500{--tw-text-opacity:1;color:rgb(94 114 228/var(--tw-text-opacity))}.text-emerald-500{--tw-text-opacity:1;color:rgb(45 206 137/var(--tw-text-opacity))}.text-gray-100{--tw-text-opacity:1;color:rgb(235 239 244/var(--tw-text-opacity))}.text-gray-300{--tw-text-opacity:1;color:rgb(210 214 218/var(--tw-text-opacity))}.text-gray-600{--tw-text-opacity:1;color:rgb(108 117 125/var(--tw-text-opacity))}.text-gray-600\/90{color:#6c757de6}.text-gray-700{--tw-text-opacity:1;color:rgb(73 80 87/var(--tw-text-opacity))}.text-gray-700\/80{color:#495057cc}.text-green-500{--tw-text-opacity:1;color:rgb(34 197 94/var(--tw-text-opacity))}.text-primary{--tw-text-opacity:1;color:rgb(11 85 119/var(--tw-text-opacity))}.text-red-500{--tw-text-opacity:1;color:rgb(245 57 57/var(--tw-text-opacity))}.text-sky-600{--tw-text-opacity:1;color:rgb(62 161 236/var(--tw-text-opacity))}.text-slate-500{--tw-text-opacity:1;color:rgb(103 116 142/var(--tw-text-opacity))}.text-slate-700{--tw-text-opacity:1;color:rgb(52 71 103/var(--tw-text-opacity))}.text-white{--tw-text-opacity:1;color:rgb(255 255 255/var(--tw-text-opacity))}.text-yellow-500{--tw-text-opacity:1;color:rgb(251 177 64/var(--tw-text-opacity))}.underline{text-decoration-line:underline}.antialiased{-webkit-font-smoothing:antialiased;-moz-osx-font-smoothing:grayscale}.opacity-0{opacity:0}.opacity-100{opacity:1}.opacity-50{opacity:.5}.opacity-60{opacity:.6}.shadow{--tw-shadow:0 1px 3px 0 #0000001a,0 1px 2px -1px #0000001a;--tw-shadow-colored:0 1px 3px 0 var(--tw-shadow-color),0 1px 2px -1px var(--tw-shadow-color)}.shadow,.shadow-3xl{box-shadow:var(--tw-ring-offset-shadow,0 0 #0000),var(--tw-ring-shadow,0 0 #0000),var(--tw-shadow)}.shadow-3xl{--tw-shadow:0 8px 26px -4px #14141426,0 8px 9px -5px #1414140f;--tw-shadow-colored:0 8px 26px -4px var(--tw-shadow-color),0 8px 9px -5px var(--tw-shadow-color)}.shadow-md{--tw-shadow:0 4px 6px #32325d1a,0 1px 3px #00000014;--tw-shadow-colored:0 4px 6px var(--tw-shadow-color),0 1px 3px var(--tw-shadow-color)}.shadow-md,.shadow-none{box-shadow:var(--tw-ring-offset-shadow,0 0 #0000),var(--tw-ring-shadow,0 0 #0000),var(--tw-shadow)}.shadow-none{--tw-shadow:0 0 #0000;--tw-shadow-colored:0 0 #0000}.shadow-sm{--tw-shadow:0 .25rem .375rem -.0625rem #1414141f,0 .125rem .25rem -.0625rem #14141412;--tw-shadow-colored:0 .25rem .375rem -.0625rem var(--tw-shadow-color),0 .125rem .25rem -.0625rem var(--tw-shadow-color)}.shadow-sm,.shadow-xl{box-shadow:var(--tw-ring-offset-shadow,0 0 #0000),var(--tw-ring-shadow,0 0 #0000),var(--tw-shadow)}.shadow-xl{--tw-shadow:0 0 2rem 0 #8898aa26;--tw-shadow-colored:0 0 2rem 0 var(--tw-shadow-color)}.shadow-xs{--tw-shadow:0 7px 14px #32325d1a,0 3px 6px #00000014;--tw-shadow-colored:0 7px 14px var(--tw-shadow-color),0 3px 6px var(--tw-shadow-color);box-shadow:var(--tw-ring-offset-shadow,0 0 #0000),var(--tw-ring-shadow,0 0 #0000),var(--tw-shadow)}.outline-none{outline:2px solid #0000;outline-offset:2px}.blur{--tw-blur:blur(8px)}.blur,.filter{filter:var(--tw-blur) var(--tw-brightness) var(--tw-contrast) var(--tw-grayscale) var(--tw-hue-rotate) var(--tw-invert) var(--tw-saturate) var(--tw-sepia) var(--tw-drop-shadow)}.transition{transition-property:color,background-color,border-color,text-decoration-color,fill,stroke,opacity,box-shadow,transform,filter,-webkit-backdrop-filter;transition-property:color,background-color,border-color,text-decoration-color,fill,stroke,opacity,box-shadow,transform,filter,backdrop-filter;transition-property:color,background-color,border-color,text-decoration-color,fill,stroke,opacity,box-shadow,transform,filter,backdrop-filter,-webkit-backdrop-filter;transition-timing-function:ease;transition-duration:.15s}.transition-all{transition-property:all;transition-timing-function:ease;transition-duration:.15s}.transition-transform{transition-property:transform;transition-timing-function:ease;transition-duration:.15s}.delay-200{transition-delay:.2s}.duration-200{transition-duration:.2s}.duration-250{transition-duration:.25s}.duration-300{transition-duration:.3s}.duration-700{transition-duration:.7s}.ease-in{transition-timing-function:ease-in}.ease-in-out{transition-timing-function:ease-in-out}.flex-wrap-inherit{flex-wrap:inherit}@font-face{font-family:Open Sans;src:url(../webfonts/OpenSans.ttf)}*{font-family:Open Sans,sans-serif!important}.ace_content,.ace_editor,.ace_editor div{font-family:Monaco,Menlo,Ubuntu Mono,Consolas,source-code-pro,monospace!important;font-size:16px!important;font-weight:400!important}.sr-only{display:none}.close-btn{display:inline-block;cursor:pointer;border-radius:.5rem;border-width:1px;--tw-border-opacity:1;border-color:rgb(245 57 57/var(--tw-border-opacity));--tw-bg-opacity:1;background-color:rgb(255 255 255/var(--tw-bg-opacity));padding:.75rem 1.5rem;text-align:center;vertical-align:middle;font-weight:700;text-transform:uppercase;line-height:1.5;letter-spacing:-.025rem;--tw-text-opacity:1;color:rgb(245 57 57/var(--tw-text-opacity));--tw-shadow:0 7px 14px #32325d1a,0 3px 6px #00000014;--tw-shadow-colored:0 7px 14px var(--tw-shadow-color),0 3px 6px var(--tw-shadow-color);transition-property:all;transition-timing-function:ease;transition-duration:.15s;transition-timing-function:ease-in}.close-btn,.close-btn:hover{box-shadow:var(--tw-ring-offset-shadow,0 0 #0000),var(--tw-ring-shadow,0 0 #0000),var(--tw-shadow)}.close-btn:hover{--tw-translate-y:-1px;transform:translate(var(--tw-translate-x),var(--tw-translate-y)) rotate(var(--tw-rotate)) skewX(var(--tw-skew-x)) skewY(var(--tw-skew-y)) scaleX(var(--tw-scale-x)) scaleY(var(--tw-scale-y));--tw-shadow:0 4px 6px #32325d1a,0 1px 3px #00000014;--tw-shadow-colored:0 4px 6px var(--tw-shadow-color),0 1px 3px var(--tw-shadow-color)}.close-btn:focus,.close-btn:hover{background-color:#fffc}.close-btn:active{opacity:.85}.close-btn:disabled{cursor:not-allowed;--tw-bg-opacity:1;--tw-text-opacity:1;color:rgb(73 80 87/var(--tw-text-opacity))}.close-btn:disabled,.close-btn:hover:disabled{border-color:#ced4da00;background-color:rgb(206 212 218/var(--tw-bg-opacity))}.close-btn:hover:disabled{--tw-translate-y:0px;transform:translate(var(--tw-translate-x),var(--tw-translate-y)) rotate(var(--tw-rotate)) skewX(var(--tw-skew-x)) skewY(var(--tw-skew-y)) scaleX(var(--tw-scale-x)) scaleY(var(--tw-scale-y));--tw-bg-opacity:1}:is(.dark .close-btn){--tw-bg-opacity:1;background-color:rgb(233 236 239/var(--tw-bg-opacity));--tw-brightness:brightness(.9)}:is(.dark .close-btn),:is(.dark .close-btn:hover){filter:var(--tw-blur) var(--tw-brightness) var(--tw-contrast) var(--tw-grayscale) var(--tw-hue-rotate) var(--tw-invert) var(--tw-saturate) var(--tw-sepia) var(--tw-drop-shadow)}:is(.dark .close-btn:hover){--tw-brightness:brightness(.75)}:is(.dark .close-btn:disabled){--tw-bg-opacity:1;--tw-text-opacity:1;color:rgb(210 214 218/var(--tw-text-opacity))}:is(.dark .close-btn:disabled),:is(.dark .close-btn:hover:disabled){border-color:#49505700;background-color:rgb(73 80 87/var(--tw-bg-opacity))}:is(.dark .close-btn:hover:disabled){--tw-translate-y:0px;transform:translate(var(--tw-translate-x),var(--tw-translate-y)) rotate(var(--tw-rotate)) skewX(var(--tw-skew-x)) skewY(var(--tw-skew-y)) scaleX(var(--tw-scale-x)) scaleY(var(--tw-scale-y));--tw-bg-opacity:1}.valid-btn{display:inline-block;cursor:pointer;border-radius:.5rem;--tw-bg-opacity:1;background-color:rgb(34 197 94/var(--tw-bg-opacity));padding:.75rem 1.5rem;text-align:center;vertical-align:middle;font-weight:700;text-transform:uppercase;line-height:1.5;letter-spacing:.025em;--tw-text-opacity:1;color:rgb(255 255 255/var(--tw-text-opacity));--tw-shadow:0 7px 14px #32325d1a,0 3px 6px #00000014;--tw-shadow-colored:0 7px 14px var(--tw-shadow-color),0 3px 6px var(--tw-shadow-color);transition-property:all;transition-timing-function:ease;transition-duration:.15s;transition-timing-function:ease-in}.valid-btn,.valid-btn:hover{box-shadow:var(--tw-ring-offset-shadow,0 0 #0000),var(--tw-ring-shadow,0 0 #0000),var(--tw-shadow)}.valid-btn:hover{--tw-translate-y:-1px;transform:translate(var(--tw-translate-x),var(--tw-translate-y)) rotate(var(--tw-rotate)) skewX(var(--tw-skew-x)) skewY(var(--tw-skew-y)) scaleX(var(--tw-scale-x)) scaleY(var(--tw-scale-y));--tw-shadow:0 4px 6px #32325d1a,0 1px 3px #00000014;--tw-shadow-colored:0 4px 6px var(--tw-shadow-color),0 1px 3px var(--tw-shadow-color)}.valid-btn:focus,.valid-btn:hover{background-color:#22c55ecc}.valid-btn:active{opacity:.85}.valid-btn:disabled{cursor:not-allowed;--tw-bg-opacity:1;--tw-text-opacity:1;color:rgb(73 80 87/var(--tw-text-opacity))}.valid-btn:disabled,.valid-btn:hover:disabled{border-color:#ced4da00;background-color:rgb(206 212 218/var(--tw-bg-opacity))}.valid-btn:hover:disabled{--tw-translate-y:0px;transform:translate(var(--tw-translate-x),var(--tw-translate-y)) rotate(var(--tw-rotate)) skewX(var(--tw-skew-x)) skewY(var(--tw-skew-y)) scaleX(var(--tw-scale-x)) scaleY(var(--tw-scale-y));--tw-bg-opacity:1}:is(.dark .valid-btn){--tw-brightness:brightness(.9);filter:var(--tw-blur) var(--tw-brightness) var(--tw-contrast) var(--tw-grayscale) var(--tw-hue-rotate) var(--tw-invert) var(--tw-saturate) var(--tw-sepia) var(--tw-drop-shadow)}:is(.dark .valid-btn:disabled){--tw-bg-opacity:1;--tw-text-opacity:1;color:rgb(210 214 218/var(--tw-text-opacity))}:is(.dark .valid-btn:disabled),:is(.dark .valid-btn:hover:disabled){border-color:#49505700;background-color:rgb(73 80 87/var(--tw-bg-opacity))}:is(.dark .valid-btn:hover:disabled){--tw-translate-y:0px;transform:translate(var(--tw-translate-x),var(--tw-translate-y)) rotate(var(--tw-rotate)) skewX(var(--tw-skew-x)) skewY(var(--tw-skew-y)) scaleX(var(--tw-scale-x)) scaleY(var(--tw-scale-y));--tw-bg-opacity:1}.delete-btn{display:inline-block;cursor:pointer;border-radius:.5rem;--tw-bg-opacity:1;background-color:rgb(245 57 57/var(--tw-bg-opacity));padding:.75rem 1.5rem;text-align:center;vertical-align:middle;font-weight:700;text-transform:uppercase;line-height:1.5;letter-spacing:.025em;--tw-text-opacity:1;color:rgb(255 255 255/var(--tw-text-opacity));--tw-shadow:0 7px 14px #32325d1a,0 3px 6px #00000014;--tw-shadow-colored:0 7px 14px var(--tw-shadow-color),0 3px 6px var(--tw-shadow-color);transition-property:all;transition-timing-function:ease;transition-duration:.15s;transition-timing-function:ease-in}.delete-btn,.delete-btn:hover{box-shadow:var(--tw-ring-offset-shadow,0 0 #0000),var(--tw-ring-shadow,0 0 #0000),var(--tw-shadow)}.delete-btn:hover{--tw-translate-y:-1px;transform:translate(var(--tw-translate-x),var(--tw-translate-y)) rotate(var(--tw-rotate)) skewX(var(--tw-skew-x)) skewY(var(--tw-skew-y)) scaleX(var(--tw-scale-x)) scaleY(var(--tw-scale-y));--tw-shadow:0 4px 6px #32325d1a,0 1px 3px #00000014;--tw-shadow-colored:0 4px 6px var(--tw-shadow-color),0 1px 3px var(--tw-shadow-color)}.delete-btn:focus,.delete-btn:hover{background-color:#f53939cc}.delete-btn:active{opacity:.85}.delete-btn:disabled{cursor:not-allowed;--tw-bg-opacity:1;--tw-text-opacity:1;color:rgb(73 80 87/var(--tw-text-opacity))}.delete-btn:disabled,.delete-btn:hover:disabled{border-color:#ced4da00;background-color:rgb(206 212 218/var(--tw-bg-opacity))}.delete-btn:hover:disabled{--tw-translate-y:0px;transform:translate(var(--tw-translate-x),var(--tw-translate-y)) rotate(var(--tw-rotate)) skewX(var(--tw-skew-x)) skewY(var(--tw-skew-y)) scaleX(var(--tw-scale-x)) scaleY(var(--tw-scale-y));--tw-bg-opacity:1}:is(.dark .delete-btn){--tw-brightness:brightness(.9);filter:var(--tw-blur) var(--tw-brightness) var(--tw-contrast) var(--tw-grayscale) var(--tw-hue-rotate) var(--tw-invert) var(--tw-saturate) var(--tw-sepia) var(--tw-drop-shadow)}:is(.dark .delete-btn:disabled){border-color:#49505700;--tw-bg-opacity:1;background-color:rgb(73 80 87/var(--tw-bg-opacity));--tw-text-opacity:1;color:rgb(210 214 218/var(--tw-text-opacity))}:is(.dark .delete-btn:hover:disabled){--tw-translate-y:0px;transform:translate(var(--tw-translate-x),var(--tw-translate-y)) rotate(var(--tw-rotate)) skewX(var(--tw-skew-x)) skewY(var(--tw-skew-y)) scaleX(var(--tw-scale-x)) scaleY(var(--tw-scale-y));border-color:#49505700;--tw-bg-opacity:1;background-color:rgb(73 80 87/var(--tw-bg-opacity))}.edit-btn{display:inline-block;cursor:pointer;border-radius:.5rem;--tw-bg-opacity:1;background-color:rgb(251 177 64/var(--tw-bg-opacity));padding:.75rem 1.5rem;text-align:center;vertical-align:middle;font-weight:700;text-transform:uppercase;line-height:1.5;letter-spacing:.025em;--tw-text-opacity:1;color:rgb(255 255 255/var(--tw-text-opacity));--tw-shadow:0 7px 14px #32325d1a,0 3px 6px #00000014;--tw-shadow-colored:0 7px 14px var(--tw-shadow-color),0 3px 6px var(--tw-shadow-color);transition-property:all;transition-timing-function:ease;transition-duration:.15s;transition-timing-function:ease-in}.edit-btn,.edit-btn:hover{box-shadow:var(--tw-ring-offset-shadow,0 0 #0000),var(--tw-ring-shadow,0 0 #0000),var(--tw-shadow)}.edit-btn:hover{--tw-translate-y:-1px;transform:translate(var(--tw-translate-x),var(--tw-translate-y)) rotate(var(--tw-rotate)) skewX(var(--tw-skew-x)) skewY(var(--tw-skew-y)) scaleX(var(--tw-scale-x)) scaleY(var(--tw-scale-y));--tw-shadow:0 4px 6px #32325d1a,0 1px 3px #00000014;--tw-shadow-colored:0 4px 6px var(--tw-shadow-color),0 1px 3px var(--tw-shadow-color)}.edit-btn:focus,.edit-btn:hover{background-color:#fbb140cc}.edit-btn:active{opacity:.85}.edit-btn:disabled{cursor:not-allowed;--tw-bg-opacity:1;--tw-text-opacity:1;color:rgb(73 80 87/var(--tw-text-opacity))}.edit-btn:disabled,.edit-btn:hover:disabled{border-color:#ced4da00;background-color:rgb(206 212 218/var(--tw-bg-opacity))}.edit-btn:hover:disabled{--tw-translate-y:0px;transform:translate(var(--tw-translate-x),var(--tw-translate-y)) rotate(var(--tw-rotate)) skewX(var(--tw-skew-x)) skewY(var(--tw-skew-y)) scaleX(var(--tw-scale-x)) scaleY(var(--tw-scale-y));--tw-bg-opacity:1}:is(.dark .edit-btn){--tw-brightness:brightness(.9);filter:var(--tw-blur) var(--tw-brightness) var(--tw-contrast) var(--tw-grayscale) var(--tw-hue-rotate) var(--tw-invert) var(--tw-saturate) var(--tw-sepia) var(--tw-drop-shadow)}:is(.dark .edit-btn:disabled){--tw-bg-opacity:1;--tw-text-opacity:1;color:rgb(210 214 218/var(--tw-text-opacity))}:is(.dark .edit-btn:disabled),:is(.dark .edit-btn:hover:disabled){border-color:#49505700;background-color:rgb(73 80 87/var(--tw-bg-opacity))}:is(.dark .edit-btn:hover:disabled){--tw-translate-y:0px;transform:translate(var(--tw-translate-x),var(--tw-translate-y)) rotate(var(--tw-rotate)) skewX(var(--tw-skew-x)) skewY(var(--tw-skew-y)) scaleX(var(--tw-scale-x)) scaleY(var(--tw-scale-y));--tw-bg-opacity:1}.info-btn{display:inline-block;cursor:pointer;border-radius:.5rem;--tw-bg-opacity:1;background-color:rgb(14 165 233/var(--tw-bg-opacity));padding:.75rem 1.5rem;text-align:center;vertical-align:middle;font-weight:700;text-transform:uppercase;line-height:1.5;letter-spacing:.025em;--tw-text-opacity:1;color:rgb(255 255 255/var(--tw-text-opacity));--tw-shadow:0 7px 14px #32325d1a,0 3px 6px #00000014;--tw-shadow-colored:0 7px 14px var(--tw-shadow-color),0 3px 6px var(--tw-shadow-color);transition-property:all;transition-timing-function:ease;transition-duration:.15s;transition-timing-function:ease-in}.info-btn,.info-btn:hover{box-shadow:var(--tw-ring-offset-shadow,0 0 #0000),var(--tw-ring-shadow,0 0 #0000),var(--tw-shadow)}.info-btn:hover{--tw-translate-y:-1px;transform:translate(var(--tw-translate-x),var(--tw-translate-y)) rotate(var(--tw-rotate)) skewX(var(--tw-skew-x)) skewY(var(--tw-skew-y)) scaleX(var(--tw-scale-x)) scaleY(var(--tw-scale-y));--tw-shadow:0 4px 6px #32325d1a,0 1px 3px #00000014;--tw-shadow-colored:0 4px 6px var(--tw-shadow-color),0 1px 3px var(--tw-shadow-color)}.info-btn:focus,.info-btn:hover{background-color:#0ea5e9cc}.info-btn:active{opacity:.85}.info-btn:disabled{cursor:not-allowed;--tw-bg-opacity:1;--tw-text-opacity:1;color:rgb(73 80 87/var(--tw-text-opacity))}.info-btn:disabled,.info-btn:hover:disabled{border-color:#ced4da00;background-color:rgb(206 212 218/var(--tw-bg-opacity))}.info-btn:hover:disabled{--tw-translate-y:0px;transform:translate(var(--tw-translate-x),var(--tw-translate-y)) rotate(var(--tw-rotate)) skewX(var(--tw-skew-x)) skewY(var(--tw-skew-y)) scaleX(var(--tw-scale-x)) scaleY(var(--tw-scale-y));--tw-bg-opacity:1}:is(.dark .info-btn){--tw-brightness:brightness(.9);filter:var(--tw-blur) var(--tw-brightness) var(--tw-contrast) var(--tw-grayscale) var(--tw-hue-rotate) var(--tw-invert) var(--tw-saturate) var(--tw-sepia) var(--tw-drop-shadow)}:is(.dark .info-btn:disabled){--tw-bg-opacity:1;--tw-text-opacity:1;color:rgb(210 214 218/var(--tw-text-opacity))}:is(.dark .info-btn:disabled),:is(.dark .info-btn:hover:disabled){border-color:#49505700;background-color:rgb(73 80 87/var(--tw-bg-opacity))}:is(.dark .info-btn:hover:disabled){--tw-translate-y:0px;transform:translate(var(--tw-translate-x),var(--tw-translate-y)) rotate(var(--tw-rotate)) skewX(var(--tw-skew-x)) skewY(var(--tw-skew-y)) scaleX(var(--tw-scale-x)) scaleY(var(--tw-scale-y));--tw-bg-opacity:1}.checkbox{position:relative;z-index:10;float:left;margin-top:.25rem;height:1.25rem;width:1.25rem;cursor:pointer;-webkit-appearance:none;-moz-appearance:none;appearance:none;border-radius:.35rem;border-width:1px;border-color:rgb(210 214 218/var(--tw-border-opacity));background-color:rgb(255 255 255/var(--tw-bg-opacity));background-size:contain;background-position:50%;background-repeat:no-repeat;vertical-align:top;font-size:1rem;line-height:1.5rem;transition-property:all;transition-timing-function:ease;transition-duration:.25s}.checkbox,.checkbox:disabled{--tw-border-opacity:1;--tw-bg-opacity:1}.checkbox:disabled{cursor:default;border-color:rgb(206 212 218/var(--tw-border-opacity));background-color:rgb(206 212 218/var(--tw-bg-opacity));--tw-text-opacity:1;color:rgb(73 80 87/var(--tw-text-opacity))}.checkbox[data-checked=true]{z-index:0;--tw-border-opacity:1;border-color:rgb(11 85 119/var(--tw-border-opacity));--tw-bg-opacity:1;background-color:rgb(11 85 119/var(--tw-bg-opacity))}.checkbox:disabled[data-checked=true]{--tw-border-opacity:1;border-color:rgb(206 212 218/var(--tw-border-opacity));--tw-bg-opacity:1;background-color:rgb(206 212 218/var(--tw-bg-opacity));--tw-text-opacity:1;color:rgb(73 80 87/var(--tw-text-opacity))}:is(.dark .checkbox){--tw-border-opacity:1;border-color:rgb(98 117 148/var(--tw-border-opacity));--tw-bg-opacity:1;background-color:rgb(52 71 103/var(--tw-bg-opacity))}:is(.dark .checkbox:disabled){--tw-border-opacity:1;border-color:rgb(37 47 64/var(--tw-border-opacity));--tw-bg-opacity:1;background-color:rgb(37 47 64/var(--tw-bg-opacity));--tw-text-opacity:1;color:rgb(210 214 218/var(--tw-text-opacity))}:is(.dark .checkbox[data-checked=true]){--tw-border-opacity:1;border-color:rgb(11 85 119/var(--tw-border-opacity));--tw-bg-opacity:1;background-color:rgb(11 85 119/var(--tw-bg-opacity))}:is(.dark .checkbox:disabled[data-checked=true]){--tw-border-opacity:1;border-color:rgb(37 47 64/var(--tw-border-opacity));--tw-bg-opacity:1;background-color:rgb(37 47 64/var(--tw-bg-opacity));--tw-text-opacity:1;color:rgb(210 214 218/var(--tw-text-opacity))}.custom-select-btn{display:flex;width:100%;align-items:center;justify-content:space-between;border-radius:.5rem;border-width:1px;border-style:solid;--tw-border-opacity:1;border-color:rgb(210 214 218/var(--tw-border-opacity));--tw-bg-opacity:1;background-color:rgb(255 255 255/var(--tw-bg-opacity));background-clip:padding-box;padding:.25rem .375rem;text-align:left;vertical-align:middle;font-size:.875rem;font-weight:400;line-height:1.4rem;--tw-text-opacity:1;color:rgb(73 80 87/var(--tw-text-opacity));transition-property:all;transition-timing-function:ease;transition-duration:.3s;transition-timing-function:ease-in-out}.custom-select-btn::-moz-placeholder{--tw-text-opacity:1;color:rgb(173 181 189/var(--tw-text-opacity))}.custom-select-btn::placeholder{--tw-text-opacity:1;color:rgb(173 181 189/var(--tw-text-opacity))}.custom-select-btn:focus{--tw-border-opacity:1;border-color:rgb(11 85 119/var(--tw-border-opacity))}.custom-select-btn:disabled{--tw-border-opacity:1;border-color:rgb(206 212 218/var(--tw-border-opacity));--tw-bg-opacity:1;background-color:rgb(206 212 218/var(--tw-bg-opacity));--tw-text-opacity:1;color:rgb(73 80 87/var(--tw-text-opacity));opacity:.75}:is(.dark .custom-select-btn){border-color:rgb(98 117 148/var(--tw-border-opacity));background-color:rgb(52 71 103/var(--tw-bg-opacity));opacity:.9}:is(.dark .custom-select-btn),:is(.dark .custom-select-btn:disabled){--tw-border-opacity:1;--tw-bg-opacity:1;--tw-text-opacity:1;color:rgb(210 214 218/var(--tw-text-opacity))}:is(.dark .custom-select-btn:disabled){border-color:rgb(37 47 64/var(--tw-border-opacity));background-color:rgb(37 47 64/var(--tw-bg-opacity))}@media (min-width:768px){.custom-select-btn{padding:.5rem .75rem}}.custom-dropdown-btn{position:relative;margin-top:0;margin-bottom:0;min-height:38px;cursor:pointer;border-radius:0;border-bottom-width:1px;border-left-width:1px;border-right-width:1px;--tw-border-opacity:1;border-color:rgb(210 214 218/var(--tw-border-opacity));--tw-bg-opacity:1;background-color:rgb(255 255 255/var(--tw-bg-opacity));padding:.5rem 1.5rem;text-align:center;vertical-align:middle;font-size:.875rem;line-height:1.5rem;line-height:1.5;letter-spacing:-.025rem;--tw-text-opacity:1;color:rgb(73 80 87/var(--tw-text-opacity));transition-property:all;transition-timing-function:ease;transition-duration:.15s;transition-timing-function:ease-in}.custom-dropdown-btn:hover{--tw-brightness:brightness(.9);filter:var(--tw-blur) var(--tw-brightness) var(--tw-contrast) var(--tw-grayscale) var(--tw-hue-rotate) var(--tw-invert) var(--tw-saturate) var(--tw-sepia) var(--tw-drop-shadow)}:is(.dark .custom-dropdown-btn){border-color:rgb(98 117 148/var(--tw-border-opacity));background-color:rgb(52 71 103/var(--tw-bg-opacity))}.active.custom-dropdown-btn,:is(.dark .custom-dropdown-btn){--tw-border-opacity:1;--tw-bg-opacity:1;--tw-text-opacity:1;color:rgb(210 214 218/var(--tw-text-opacity))}.active.custom-dropdown-btn{position:relative;margin-top:0;margin-bottom:0;min-height:38px;cursor:pointer;border-radius:0;border-bottom-width:1px;border-left-width:1px;border-right-width:1px;border-color:rgb(210 214 218/var(--tw-border-opacity));background-color:rgb(11 85 119/var(--tw-bg-opacity));padding:.5rem 1.5rem;text-align:center;vertical-align:middle;font-size:.875rem;line-height:1.5rem;line-height:1.5;letter-spacing:-.025rem;transition-property:all;transition-timing-function:ease;transition-duration:.15s;transition-timing-function:ease-in}.active.custom-dropdown-btn:hover{--tw-brightness:brightness(.9);filter:var(--tw-blur) var(--tw-brightness) var(--tw-contrast) var(--tw-grayscale) var(--tw-hue-rotate) var(--tw-invert) var(--tw-saturate) var(--tw-sepia) var(--tw-drop-shadow)}:is(.dark .active.custom-dropdown-btn){border-color:rgb(98 117 148/var(--tw-border-opacity));background-color:rgb(11 85 119/var(--tw-bg-opacity));color:rgb(210 214 218/var(--tw-text-opacity))}.regular-input,:is(.dark .active.custom-dropdown-btn){--tw-border-opacity:1;--tw-bg-opacity:1;--tw-text-opacity:1}.regular-input{display:block;width:100%;-webkit-appearance:none;-moz-appearance:none;appearance:none;border-radius:.5rem;border-width:1px;border-style:solid;border-color:rgb(210 214 218/var(--tw-border-opacity));background-color:rgb(255 255 255/var(--tw-bg-opacity));background-clip:padding-box;padding:.25rem .375rem;font-size:.875rem;font-weight:400;line-height:1.4rem;color:rgb(73 80 87/var(--tw-text-opacity));outline:2px solid #0000;outline-offset:2px;transition-property:all;transition-timing-function:ease;transition-duration:.15s;transition-timing-function:ease-in}.regular-input::-moz-placeholder{--tw-text-opacity:1;color:rgb(173 181 189/var(--tw-text-opacity))}.regular-input::placeholder{--tw-text-opacity:1;color:rgb(173 181 189/var(--tw-text-opacity))}.regular-input:focus{border-color:#d2d6da00;--tw-ring-offset-shadow:var(--tw-ring-inset) 0 0 0 var(--tw-ring-offset-width) var(--tw-ring-offset-color);--tw-ring-shadow:var(--tw-ring-inset) 0 0 0 calc(1px + var(--tw-ring-offset-width)) var(--tw-ring-color);box-shadow:var(--tw-ring-offset-shadow),var(--tw-ring-shadow),var(--tw-shadow,0 0 #0000)}.regular-input:valid:focus{--tw-ring-opacity:1;--tw-ring-color:rgb(34 197 94/var(--tw-ring-opacity))}.regular-input:invalid:focus{--tw-ring-opacity:1;--tw-ring-color:rgb(245 57 57/var(--tw-ring-opacity))}.regular-input:disabled{--tw-bg-opacity:1;background-color:rgb(206 212 218/var(--tw-bg-opacity));--tw-text-opacity:1;color:rgb(73 80 87/var(--tw-text-opacity));opacity:.75}:is(.dark .regular-input){border-color:rgb(98 117 148/var(--tw-border-opacity));background-color:rgb(52 71 103/var(--tw-bg-opacity));opacity:.9}:is(.dark .regular-input),:is(.dark .regular-input:disabled){--tw-border-opacity:1;--tw-bg-opacity:1;--tw-text-opacity:1;color:rgb(210 214 218/var(--tw-text-opacity))}:is(.dark .regular-input:disabled){border-color:rgb(37 47 64/var(--tw-border-opacity));background-color:rgb(37 47 64/var(--tw-bg-opacity))}@media (min-width:768px){.regular-input{padding:.5rem .75rem}}.input-title{margin:0;font-size:.875rem;line-height:1.5rem;font-weight:700;transition-property:color,background-color,border-color,text-decoration-color,fill,stroke,opacity,box-shadow,transform,filter,-webkit-backdrop-filter;transition-property:color,background-color,border-color,text-decoration-color,fill,stroke,opacity,box-shadow,transform,filter,backdrop-filter;transition-property:color,background-color,border-color,text-decoration-color,fill,stroke,opacity,box-shadow,transform,filter,backdrop-filter,-webkit-backdrop-filter;transition-timing-function:ease;transition-duration:.3s;transition-timing-function:ease-in-out}:is(.dark .input-title){--tw-text-opacity:1;color:rgb(210 214 218/var(--tw-text-opacity));opacity:.9}.popover-settings-container{position:absolute;left:0;bottom:0;z-index:50;--tw-translate-y:-1.75rem;transform:translate(var(--tw-translate-x),var(--tw-translate-y)) rotate(var(--tw-rotate)) skewX(var(--tw-skew-x)) skewY(var(--tw-skew-y)) scaleX(var(--tw-scale-x)) scaleY(var(--tw-scale-y));border-radius:.375rem;--tw-bg-opacity:1;background-color:rgb(94 114 228/var(--tw-bg-opacity));padding:.75rem;transition-property:all;transition-property:color,background-color,border-color,text-decoration-color,fill,stroke,opacity,box-shadow,transform,filter,-webkit-backdrop-filter;transition-property:color,background-color,border-color,text-decoration-color,fill,stroke,opacity,box-shadow,transform,filter,backdrop-filter;transition-property:color,background-color,border-color,text-decoration-color,fill,stroke,opacity,box-shadow,transform,filter,backdrop-filter,-webkit-backdrop-filter;transition-timing-function:ease;transition-duration:.5s}:is(.dark .popover-settings-container){--tw-brightness:brightness(.9);filter:var(--tw-blur) var(--tw-brightness) var(--tw-contrast) var(--tw-grayscale) var(--tw-hue-rotate) var(--tw-invert) var(--tw-saturate) var(--tw-sepia) var(--tw-drop-shadow)}.popover-settings-text{margin:0;font-size:.875rem;line-height:1.5rem;font-weight:700;--tw-text-opacity:1;color:rgb(255 255 255/var(--tw-text-opacity));transition-property:color,background-color,border-color,text-decoration-color,fill,stroke,opacity,box-shadow,transform,filter,-webkit-backdrop-filter;transition-property:color,background-color,border-color,text-decoration-color,fill,stroke,opacity,box-shadow,transform,filter,backdrop-filter;transition-property:color,background-color,border-color,text-decoration-color,fill,stroke,opacity,box-shadow,transform,filter,backdrop-filter,-webkit-backdrop-filter;transition-timing-function:ease;transition-duration:.3s;transition-timing-function:ease-in-out}:is(.dark .popover-settings-text){--tw-text-opacity:1;color:rgb(235 239 244/var(--tw-text-opacity));opacity:.9}.popover-settings-svg{margin-left:.5rem;height:1.25rem;width:1.25rem;cursor:pointer;fill:#5e72e4}.popover-settings-svg:hover{--tw-brightness:brightness(.75);filter:var(--tw-blur) var(--tw-brightness) var(--tw-contrast) var(--tw-grayscale) var(--tw-hue-rotate) var(--tw-invert) var(--tw-saturate) var(--tw-sepia) var(--tw-drop-shadow)}.active.settings-tabs-tab-btn{position:relative;z-index:10;margin-top:.25rem;margin-bottom:.25rem;cursor:pointer;border-radius:0;border-width:1px;--tw-border-opacity:1;border-color:rgb(11 85 119/var(--tw-border-opacity));--tw-bg-opacity:1;background-color:rgb(255 255 255/var(--tw-bg-opacity));padding:.75rem;text-align:center;vertical-align:middle;font-size:.875rem;line-height:1.5rem;font-weight:700;text-transform:uppercase;line-height:1.5;letter-spacing:-.025rem;--tw-shadow:0 7px 14px #32325d1a,0 3px 6px #00000014;--tw-shadow-colored:0 7px 14px var(--tw-shadow-color),0 3px 6px var(--tw-shadow-color);box-shadow:var(--tw-ring-offset-shadow,0 0 #0000),var(--tw-ring-shadow,0 0 #0000),var(--tw-shadow);--tw-brightness:brightness(.9);filter:var(--tw-blur) var(--tw-brightness) var(--tw-contrast) var(--tw-grayscale) var(--tw-hue-rotate) var(--tw-invert) var(--tw-saturate) var(--tw-sepia) var(--tw-drop-shadow);transition-property:all;transition-timing-function:ease;transition-duration:.15s;transition-timing-function:ease-in}.active.settings-tabs-tab-btn:hover{--tw-bg-opacity:1;background-color:rgb(235 239 244/var(--tw-bg-opacity));--tw-shadow:0 4px 6px #32325d1a,0 1px 3px #00000014;--tw-shadow-colored:0 4px 6px var(--tw-shadow-color),0 1px 3px var(--tw-shadow-color);box-shadow:var(--tw-ring-offset-shadow,0 0 #0000),var(--tw-ring-shadow,0 0 #0000),var(--tw-shadow)}:is(.dark .active.settings-tabs-tab-btn){--tw-border-opacity:1;border-color:rgb(98 117 148/var(--tw-border-opacity));--tw-bg-opacity:1;background-color:rgb(52 71 103/var(--tw-bg-opacity))}:is(.dark .active.settings-tabs-tab-btn:hover){--tw-bg-opacity:1;background-color:rgb(58 65 111/var(--tw-bg-opacity))}.settings-tabs-tab-btn{position:relative;margin-top:.25rem;margin-bottom:.25rem;cursor:pointer;border-radius:0;border-width:1px;--tw-border-opacity:1;border-color:rgb(11 85 119/var(--tw-border-opacity));--tw-bg-opacity:1;background-color:rgb(255 255 255/var(--tw-bg-opacity));padding:.75rem;text-align:center;vertical-align:middle;font-size:.875rem;line-height:1.5rem;font-weight:700;text-transform:uppercase;line-height:1.5;letter-spacing:-.025rem;--tw-shadow:0 7px 14px #32325d1a,0 3px 6px #00000014;--tw-shadow-colored:0 7px 14px var(--tw-shadow-color),0 3px 6px var(--tw-shadow-color);box-shadow:var(--tw-ring-offset-shadow,0 0 #0000),var(--tw-ring-shadow,0 0 #0000),var(--tw-shadow);transition-property:all;transition-timing-function:ease;transition-duration:.15s;transition-timing-function:ease-in}.settings-tabs-tab-btn:hover{--tw-bg-opacity:1;background-color:rgb(235 239 244/var(--tw-bg-opacity));--tw-shadow:0 4px 6px #32325d1a,0 1px 3px #00000014;--tw-shadow-colored:0 4px 6px var(--tw-shadow-color),0 1px 3px var(--tw-shadow-color);box-shadow:var(--tw-ring-offset-shadow,0 0 #0000),var(--tw-ring-shadow,0 0 #0000),var(--tw-shadow)}:is(.dark .settings-tabs-tab-btn){--tw-border-opacity:1;border-color:rgb(98 117 148/var(--tw-border-opacity));--tw-bg-opacity:1;background-color:rgb(52 71 103/var(--tw-bg-opacity))}:is(.dark .settings-tabs-tab-btn:hover){--tw-bg-opacity:1;background-color:rgb(58 65 111/var(--tw-bg-opacity))}.settings-tabs-name{padding-left:.75rem;padding-right:.5rem;--tw-text-opacity:1;color:rgb(11 85 119/var(--tw-text-opacity));transition-property:color,background-color,border-color,text-decoration-color,fill,stroke,opacity,box-shadow,transform,filter,-webkit-backdrop-filter;transition-property:color,background-color,border-color,text-decoration-color,fill,stroke,opacity,box-shadow,transform,filter,backdrop-filter;transition-property:color,background-color,border-color,text-decoration-color,fill,stroke,opacity,box-shadow,transform,filter,backdrop-filter,-webkit-backdrop-filter;transition-timing-function:ease;transition-duration:.3s;transition-timing-function:ease-in-out}:is(.dark .settings-tabs-name){--tw-text-opacity:1;color:rgb(210 214 218/var(--tw-text-opacity));opacity:.9}.settings-tabs-popover-container{position:absolute;top:60px;left:0;z-index:50;min-width:150px;border-radius:.375rem;--tw-bg-opacity:1;background-color:rgb(94 114 228/var(--tw-bg-opacity));padding:.75rem;transition-property:color,background-color,border-color,text-decoration-color,fill,stroke,opacity,box-shadow,transform,filter,-webkit-backdrop-filter;transition-property:color,background-color,border-color,text-decoration-color,fill,stroke,opacity,box-shadow,transform,filter,backdrop-filter;transition-property:color,background-color,border-color,text-decoration-color,fill,stroke,opacity,box-shadow,transform,filter,backdrop-filter,-webkit-backdrop-filter;transition-timing-function:ease;transition-duration:.15s}:is(.dark .settings-tabs-popover-container){--tw-brightness:brightness(.9);filter:var(--tw-blur) var(--tw-brightness) var(--tw-contrast) var(--tw-grayscale) var(--tw-hue-rotate) var(--tw-invert) var(--tw-saturate) var(--tw-sepia) var(--tw-drop-shadow)}.settings-tabs-popover-text{margin:0;font-size:.875rem;line-height:1.5rem;font-weight:700;--tw-text-opacity:1;color:rgb(255 255 255/var(--tw-text-opacity))}.settings-tabs-mobile-btn{margin-top:.25rem;margin-bottom:.25rem;display:flex;width:100%;cursor:pointer;align-items:center;justify-content:space-between;border-radius:.5rem;border-width:1px;--tw-border-opacity:1;border-color:rgb(11 85 119/var(--tw-border-opacity));--tw-bg-opacity:1;background-color:rgb(255 255 255/var(--tw-bg-opacity));padding:.75rem 1.5rem;text-align:center;vertical-align:middle;font-size:.875rem;line-height:1.5rem;font-weight:700;text-transform:uppercase;line-height:1.5;letter-spacing:-.025rem;--tw-shadow:0 7px 14px #32325d1a,0 3px 6px #00000014;--tw-shadow-colored:0 7px 14px var(--tw-shadow-color),0 3px 6px var(--tw-shadow-color);box-shadow:var(--tw-ring-offset-shadow,0 0 #0000),var(--tw-ring-shadow,0 0 #0000),var(--tw-shadow);transition-property:all;transition-timing-function:ease;transition-duration:.15s;transition-timing-function:ease-in}.settings-tabs-mobile-btn:hover{--tw-translate-y:-1px;transform:translate(var(--tw-translate-x),var(--tw-translate-y)) rotate(var(--tw-rotate)) skewX(var(--tw-skew-x)) skewY(var(--tw-skew-y)) scaleX(var(--tw-scale-x)) scaleY(var(--tw-scale-y));--tw-bg-opacity:1;background-color:rgb(248 249 250/var(--tw-bg-opacity));--tw-shadow:0 4px 6px #32325d1a,0 1px 3px #00000014;--tw-shadow-colored:0 4px 6px var(--tw-shadow-color),0 1px 3px var(--tw-shadow-color);box-shadow:var(--tw-ring-offset-shadow,0 0 #0000),var(--tw-ring-shadow,0 0 #0000),var(--tw-shadow)}:is(.dark .settings-tabs-mobile-btn){--tw-border-opacity:1;border-color:rgb(98 117 148/var(--tw-border-opacity));--tw-bg-opacity:1;background-color:rgb(52 71 103/var(--tw-bg-opacity))}:is(.dark .settings-tabs-mobile-btn:hover){--tw-brightness:brightness(.95);filter:var(--tw-blur) var(--tw-brightness) var(--tw-contrast) var(--tw-grayscale) var(--tw-hue-rotate) var(--tw-invert) var(--tw-saturate) var(--tw-sepia) var(--tw-drop-shadow)}.settings-tabs-mobile-btn-text{--tw-text-opacity:1;color:rgb(11 85 119/var(--tw-text-opacity));transition-property:color,background-color,border-color,text-decoration-color,fill,stroke,opacity,box-shadow,transform,filter,-webkit-backdrop-filter;transition-property:color,background-color,border-color,text-decoration-color,fill,stroke,opacity,box-shadow,transform,filter,backdrop-filter;transition-property:color,background-color,border-color,text-decoration-color,fill,stroke,opacity,box-shadow,transform,filter,backdrop-filter,-webkit-backdrop-filter;transition-timing-function:ease;transition-duration:.3s;transition-timing-function:ease-in-out}:is(.dark .settings-tabs-mobile-btn-text){--tw-text-opacity:1;color:rgb(210 214 218/var(--tw-text-opacity));opacity:.9}.active.settings-tabs-mobile-dropdown-btn{position:relative;z-index:1000;margin-top:0;margin-bottom:0;cursor:pointer;border-radius:0;--tw-border-opacity:1;border-color:rgb(210 214 218/var(--tw-border-opacity));--tw-bg-opacity:1;background-color:rgb(11 85 119/var(--tw-bg-opacity));padding:.5rem 1.5rem;text-align:center;vertical-align:middle;font-size:.875rem;line-height:1.5rem;line-height:1.5;letter-spacing:-.025rem;--tw-text-opacity:1;color:rgb(210 214 218/var(--tw-text-opacity));transition-property:all;transition-timing-function:ease;transition-duration:.15s;transition-timing-function:ease-in}.active.settings-tabs-mobile-dropdown-btn:hover{--tw-brightness:brightness(.9);filter:var(--tw-blur) var(--tw-brightness) var(--tw-contrast) var(--tw-grayscale) var(--tw-hue-rotate) var(--tw-invert) var(--tw-saturate) var(--tw-sepia) var(--tw-drop-shadow)}:is(.dark .active.settings-tabs-mobile-dropdown-btn){--tw-border-opacity:1;border-color:rgb(98 117 148/var(--tw-border-opacity));--tw-bg-opacity:1;background-color:rgb(11 85 119/var(--tw-bg-opacity));--tw-text-opacity:1;color:rgb(210 214 218/var(--tw-text-opacity))}:is(.dark .active.settings-tabs-mobile-dropdown-btn:hover){--tw-brightness:brightness(.9);filter:var(--tw-blur) var(--tw-brightness) var(--tw-contrast) var(--tw-grayscale) var(--tw-hue-rotate) var(--tw-invert) var(--tw-saturate) var(--tw-sepia) var(--tw-drop-shadow)}.first.settings-tabs-mobile-dropdown-btn{border-top-left-radius:.25rem;border-top-right-radius:.25rem;border-width:1px}.settings-tabs-mobile-dropdown-btn{position:relative;margin-top:0;margin-bottom:0;display:flex;cursor:pointer;justify-content:space-between;border-radius:0;border-bottom-width:1px;border-left-width:1px;border-right-width:1px;--tw-border-opacity:1;border-color:rgb(210 214 218/var(--tw-border-opacity));--tw-bg-opacity:1;background-color:rgb(255 255 255/var(--tw-bg-opacity));padding:.5rem 1.5rem;text-align:center;vertical-align:middle;font-size:.875rem;line-height:1.5rem;line-height:1.5;letter-spacing:-.025rem;--tw-text-opacity:1;color:rgb(73 80 87/var(--tw-text-opacity));transition-property:all;transition-timing-function:ease;transition-duration:.15s;transition-timing-function:ease-in}.settings-tabs-mobile-dropdown-btn:hover{--tw-brightness:brightness(.9);filter:var(--tw-blur) var(--tw-brightness) var(--tw-contrast) var(--tw-grayscale) var(--tw-hue-rotate) var(--tw-invert) var(--tw-saturate) var(--tw-sepia) var(--tw-drop-shadow)}:is(.dark .settings-tabs-mobile-dropdown-btn){--tw-border-opacity:1;border-color:rgb(98 117 148/var(--tw-border-opacity));--tw-bg-opacity:1;background-color:rgb(52 71 103/var(--tw-bg-opacity));--tw-text-opacity:1;color:rgb(210 214 218/var(--tw-text-opacity))}:is(.dark .settings-tabs-mobile-dropdown-btn:hover){--tw-brightness:brightness(.9);filter:var(--tw-blur) var(--tw-brightness) var(--tw-contrast) var(--tw-grayscale) var(--tw-hue-rotate) var(--tw-invert) var(--tw-saturate) var(--tw-sepia) var(--tw-drop-shadow)}.first-letter\:absolute:first-letter{position:absolute}.first-letter\:w-full:first-letter{width:100%}.placeholder\:text-gray-500::-moz-placeholder{--tw-text-opacity:1;color:rgb(173 181 189/var(--tw-text-opacity))}.placeholder\:text-gray-500::placeholder{--tw-text-opacity:1;color:rgb(173 181 189/var(--tw-text-opacity))}.before\:float-left:before{content:var(--tw-content);float:left}.before\:pr-2:before{content:var(--tw-content);padding-right:.5rem}.before\:text-white:before{content:var(--tw-content);--tw-text-opacity:1;color:rgb(255 255 255/var(--tw-text-opacity))}.before\:content-\[\'\/\'\]:before{--tw-content:"/";content:var(--tw-content)}.after\:absolute:after{content:var(--tw-content);position:absolute}.after\:top-px:after{content:var(--tw-content);top:1px}.after\:float-right:after{content:var(--tw-content);float:right}.after\:h-4:after{content:var(--tw-content);height:1rem}.after\:w-4:after{content:var(--tw-content);width:1rem}.after\:translate-x-px:after{content:var(--tw-content);--tw-translate-x:1px;transform:translate(var(--tw-translate-x),var(--tw-translate-y)) rotate(var(--tw-rotate)) skewX(var(--tw-skew-x)) skewY(var(--tw-skew-y)) scaleX(var(--tw-scale-x)) scaleY(var(--tw-scale-y))}.after\:rounded-circle:after{content:var(--tw-content);border-radius:50%}.after\:bg-white:after{content:var(--tw-content);--tw-bg-opacity:1;background-color:rgb(255 255 255/var(--tw-bg-opacity))}.after\:pl-2:after{content:var(--tw-content);padding-left:.5rem}.after\:text-gray-600:after{content:var(--tw-content);--tw-text-opacity:1;color:rgb(108 117 125/var(--tw-text-opacity))}.after\:shadow-2xl:after{content:var(--tw-content);--tw-shadow:0 .3125rem .625rem 0 #0000001f;--tw-shadow-colored:0 .3125rem .625rem 0 var(--tw-shadow-color);box-shadow:var(--tw-ring-offset-shadow,0 0 #0000),var(--tw-ring-shadow,0 0 #0000),var(--tw-shadow)}.after\:duration-300:after{content:var(--tw-content);transition-duration:.3s}.after\:content-\[\'\'\]:after{--tw-content:"";content:var(--tw-content)}.after\:content-\[\'\/\'\]:after{--tw-content:"/";content:var(--tw-content)}.checked\:z-0:checked{z-index:0}.checked\:border-primary:checked{--tw-border-opacity:1;border-color:rgb(11 85 119/var(--tw-border-opacity))}.checked\:bg-primary:checked{--tw-bg-opacity:1;background-color:rgb(11 85 119/var(--tw-bg-opacity))}.checked\:bg-none:checked{background-image:none}.checked\:bg-right:checked{background-position:100%}.checked\:after\:translate-x-5:checked:after{--tw-translate-x:1.25rem}.checked\:after\:translate-x-5:checked:after,.checked\:after\:translate-x-5\.3:checked:after{content:var(--tw-content);transform:translate(var(--tw-translate-x),var(--tw-translate-y)) rotate(var(--tw-rotate)) skewX(var(--tw-skew-x)) skewY(var(--tw-skew-y)) scaleX(var(--tw-scale-x)) scaleY(var(--tw-scale-y))}.checked\:after\:translate-x-5\.3:checked:after{--tw-translate-x:1.3rem}.valid\:\!border-red-500:valid{--tw-border-opacity:1!important;border-color:rgb(245 57 57/var(--tw-border-opacity))!important}.hover\:-translate-y-0:hover{--tw-translate-y:-0px}.hover\:-translate-y-0:hover,.hover\:-translate-y-0\.4:hover{transform:translate(var(--tw-translate-x),var(--tw-translate-y)) rotate(var(--tw-rotate)) skewX(var(--tw-skew-x)) skewY(var(--tw-skew-y)) scaleX(var(--tw-scale-x)) scaleY(var(--tw-scale-y))}.hover\:-translate-y-0\.4:hover{--tw-translate-y:-0.1rem}.hover\:-translate-y-px:hover{--tw-translate-y:-1px}.hover\:-translate-y-px:hover,.hover\:scale-102:hover{transform:translate(var(--tw-translate-x),var(--tw-translate-y)) rotate(var(--tw-rotate)) skewX(var(--tw-skew-x)) skewY(var(--tw-skew-y)) scaleX(var(--tw-scale-x)) scaleY(var(--tw-scale-y))}.hover\:scale-102:hover{--tw-scale-x:1.02;--tw-scale-y:1.02}.hover\:rounded-lg:hover{border-radius:.5rem}.hover\:bg-emerald-500\/80:hover{background-color:#2dce89cc}.hover\:bg-gray-100:hover{--tw-bg-opacity:1;background-color:rgb(235 239 244/var(--tw-bg-opacity))}.hover\:bg-gray-300:hover{--tw-bg-opacity:1;background-color:rgb(210 214 218/var(--tw-bg-opacity))}.hover\:bg-green-500\/80:hover{background-color:#22c55ecc}.hover\:bg-primary\/30:hover{background-color:#0b55774d}.hover\:bg-primary\/5:hover{background-color:#0b55770d}.hover\:bg-primary\/80:hover{background-color:#0b5577cc}.hover\:bg-red-500\/80:hover{background-color:#f53939cc}.hover\:bg-sky-500\/80:hover{background-color:#0ea5e9cc}.hover\:bg-yellow-500\/80:hover{background-color:#fbb140cc}.hover\:italic:hover{font-style:italic}.hover\:no-underline:hover{text-decoration-line:none}.hover\:opacity-80:hover{opacity:.8}.hover\:shadow-md:hover{--tw-shadow:0 4px 6px #32325d1a,0 1px 3px #00000014;--tw-shadow-colored:0 4px 6px var(--tw-shadow-color),0 1px 3px var(--tw-shadow-color);box-shadow:var(--tw-ring-offset-shadow,0 0 #0000),var(--tw-ring-shadow,0 0 #0000),var(--tw-shadow)}.hover\:brightness-75:hover{--tw-brightness:brightness(.75)}.hover\:brightness-75:hover,.hover\:brightness-90:hover{filter:var(--tw-blur) var(--tw-brightness) var(--tw-contrast) var(--tw-grayscale) var(--tw-hue-rotate) var(--tw-invert) var(--tw-saturate) var(--tw-sepia) var(--tw-drop-shadow)}.hover\:brightness-90:hover{--tw-brightness:brightness(.9)}.hover\:brightness-95:hover{--tw-brightness:brightness(.95);filter:var(--tw-blur) var(--tw-brightness) var(--tw-contrast) var(--tw-grayscale) var(--tw-hue-rotate) var(--tw-invert) var(--tw-saturate) var(--tw-sepia) var(--tw-drop-shadow)}.focus\:\!border-red-500:focus{--tw-border-opacity:1!important;border-color:rgb(245 57 57/var(--tw-border-opacity))!important}.focus\:border-green-500:focus{--tw-border-opacity:1;border-color:rgb(34 197 94/var(--tw-border-opacity))}.focus\:border-primary:focus{--tw-border-opacity:1;border-color:rgb(11 85 119/var(--tw-border-opacity))}.focus\:bg-emerald-500\/80:focus{background-color:#2dce89cc}.focus\:bg-green-500\/80:focus{background-color:#22c55ecc}.focus\:bg-primary\/80:focus{background-color:#0b5577cc}.focus\:bg-red-500\/80:focus{background-color:#f53939cc}.focus\:bg-sky-500\/80:focus{background-color:#0ea5e9cc}.focus\:bg-yellow-500\/80:focus{background-color:#fbb140cc}.focus\:\!ring-red-500:focus{--tw-ring-opacity:1!important;--tw-ring-color:rgb(245 57 57/var(--tw-ring-opacity))!important}.focus\:valid\:\!border-red-500:valid:focus{--tw-border-opacity:1!important;border-color:rgb(245 57 57/var(--tw-border-opacity))!important}.focus\:valid\:border-green-500:valid:focus{--tw-border-opacity:1;border-color:rgb(34 197 94/var(--tw-border-opacity))}.focus\:valid\:\!ring-red-500:valid:focus{--tw-ring-opacity:1!important;--tw-ring-color:rgb(245 57 57/var(--tw-ring-opacity))!important}.focus\:invalid\:border-red-500:invalid:focus{--tw-border-opacity:1;border-color:rgb(245 57 57/var(--tw-border-opacity))}.focus\:file\:invalid\:border-red-500:invalid::file-selector-button:focus{--tw-border-opacity:1;border-color:rgb(245 57 57/var(--tw-border-opacity))}.active\:\!border-red-500:active{--tw-border-opacity:1!important;border-color:rgb(245 57 57/var(--tw-border-opacity))!important}.active\:opacity-85:active{opacity:.85}.active\:valid\:\!border-red-500:valid:active{--tw-border-opacity:1!important;border-color:rgb(245 57 57/var(--tw-border-opacity))!important}.disabled\:cursor-not-allowed:disabled{cursor:not-allowed}.disabled\:border-gray-400:disabled{--tw-border-opacity:1;border-color:rgb(206 212 218/var(--tw-border-opacity))}.disabled\:border-gray-400\/0:disabled{border-color:#ced4da00}.disabled\:bg-gray-400:disabled{--tw-bg-opacity:1;background-color:rgb(206 212 218/var(--tw-bg-opacity))}.disabled\:text-gray-700:disabled{--tw-text-opacity:1;color:rgb(73 80 87/var(--tw-text-opacity))}.disabled\:opacity-75:disabled{opacity:.75}.disabled\:hover\:translate-y-0:hover:disabled{--tw-translate-y:0px;transform:translate(var(--tw-translate-x),var(--tw-translate-y)) rotate(var(--tw-rotate)) skewX(var(--tw-skew-x)) skewY(var(--tw-skew-y)) scaleX(var(--tw-scale-x)) scaleY(var(--tw-scale-y))}.disabled\:hover\:border-gray-400\/0:hover:disabled{border-color:#ced4da00}.disabled\:hover\:bg-gray-400:hover:disabled{--tw-bg-opacity:1;background-color:rgb(206 212 218/var(--tw-bg-opacity))}:is(.dark .dark\:inline){display:inline}:is(.dark .dark\:hidden){display:none}:is(.dark .dark\:border-gray-700){--tw-border-opacity:1;border-color:rgb(73 80 87/var(--tw-border-opacity))}:is(.dark .dark\:border-slate-600){--tw-border-opacity:1;border-color:rgb(98 117 148/var(--tw-border-opacity))}:is(.dark .dark\:border-slate-800){--tw-border-opacity:1;border-color:rgb(58 65 111/var(--tw-border-opacity))}:is(.dark .dark\:bg-gray-800){--tw-bg-opacity:1;background-color:rgb(37 47 64/var(--tw-bg-opacity))}:is(.dark .dark\:bg-green-500\/90){background-color:#22c55ee6}:is(.dark .dark\:bg-primary){--tw-bg-opacity:1;background-color:rgb(11 85 119/var(--tw-bg-opacity))}:is(.dark .dark\:bg-primary\/50){background-color:#0b557780}:is(.dark .dark\:bg-red-500\/90){background-color:#f53939e6}:is(.dark .dark\:bg-slate-700){--tw-bg-opacity:1;background-color:rgb(52 71 103/var(--tw-bg-opacity))}:is(.dark .dark\:bg-slate-700\/50){background-color:#34476780}:is(.dark .dark\:bg-slate-850){--tw-bg-opacity:1;background-color:rgb(17 28 68/var(--tw-bg-opacity))}:is(.dark .dark\:bg-slate-900){--tw-bg-opacity:1;background-color:rgb(5 17 57/var(--tw-bg-opacity))}:is(.dark .dark\:bg-slate-900\/30){background-color:#0511394d}:is(.dark .dark\:bg-gradient-to-r){background-image:linear-gradient(to right,var(--tw-gradient-stops))}:is(.dark .dark\:from-transparent){--tw-gradient-from:#0000 var(--tw-gradient-from-position);--tw-gradient-to:#0000 var(--tw-gradient-to-position);--tw-gradient-stops:var(--tw-gradient-from),var(--tw-gradient-to)}:is(.dark .dark\:via-white){--tw-gradient-to:#fff0 var(--tw-gradient-to-position);--tw-gradient-stops:var(--tw-gradient-from),#fff var(--tw-gradient-via-position),var(--tw-gradient-to)}:is(.dark .dark\:to-transparent){--tw-gradient-to:#0000 var(--tw-gradient-to-position)}:is(.dark .dark\:fill-blue-500){fill:#5e72e4}:is(.dark .dark\:fill-gray-300){fill:#d2d6da}:is(.dark .dark\:fill-gray-500){fill:#adb5bd}:is(.dark .dark\:fill-gray-600){fill:#6c757d}:is(.dark .dark\:stroke-amber-500){stroke:#f59e0b}:is(.dark .dark\:stroke-gray-400){stroke:#ced4da}:is(.dark .dark\:stroke-gray-600){stroke:#6c757d}:is(.dark .dark\:stroke-red-500){stroke:#f53939}:is(.dark .dark\:text-gray-100){--tw-text-opacity:1;color:rgb(235 239 244/var(--tw-text-opacity))}:is(.dark .dark\:text-gray-200){--tw-text-opacity:1;color:rgb(233 236 239/var(--tw-text-opacity))}:is(.dark .dark\:text-gray-300){--tw-text-opacity:1;color:rgb(210 214 218/var(--tw-text-opacity))}:is(.dark .dark\:text-gray-400){--tw-text-opacity:1;color:rgb(206 212 218/var(--tw-text-opacity))}:is(.dark .dark\:text-gray-500){--tw-text-opacity:1;color:rgb(173 181 189/var(--tw-text-opacity))}:is(.dark .dark\:text-red-500){--tw-text-opacity:1;color:rgb(245 57 57/var(--tw-text-opacity))}:is(.dark .dark\:text-white){--tw-text-opacity:1;color:rgb(255 255 255/var(--tw-text-opacity))}:is(.dark .dark\:text-white\/80){color:#fffc}:is(.dark .dark\:text-white\/90){color:#ffffffe6}:is(.dark .dark\:opacity-60){opacity:.6}:is(.dark .dark\:opacity-75){opacity:.75}:is(.dark .dark\:opacity-80){opacity:.8}:is(.dark .dark\:opacity-90){opacity:.9}:is(.dark .dark\:shadow-dark-xl){--tw-shadow:0 2px 2px 0 #00000024,0 3px 1px -2px #0003,0 1px 5px 0 #0000001f;--tw-shadow-colored:0 2px 2px 0 var(--tw-shadow-color),0 3px 1px -2px var(--tw-shadow-color),0 1px 5px 0 var(--tw-shadow-color)}:is(.dark .dark\:shadow-dark-xl),:is(.dark .dark\:shadow-none){box-shadow:var(--tw-ring-offset-shadow,0 0 #0000),var(--tw-ring-shadow,0 0 #0000),var(--tw-shadow)}:is(.dark .dark\:shadow-none){--tw-shadow:0 0 #0000;--tw-shadow-colored:0 0 #0000}:is(.dark .dark\:brightness-110){--tw-brightness:brightness(1.1)}:is(.dark .dark\:brightness-110),:is(.dark .dark\:brightness-125){filter:var(--tw-blur) var(--tw-brightness) var(--tw-contrast) var(--tw-grayscale) var(--tw-hue-rotate) var(--tw-invert) var(--tw-saturate) var(--tw-sepia) var(--tw-drop-shadow)}:is(.dark .dark\:brightness-125){--tw-brightness:brightness(1.25)}:is(.dark .dark\:brightness-150){--tw-brightness:brightness(1.5)}:is(.dark .dark\:brightness-150),:is(.dark .dark\:brightness-90){filter:var(--tw-blur) var(--tw-brightness) var(--tw-contrast) var(--tw-grayscale) var(--tw-hue-rotate) var(--tw-invert) var(--tw-saturate) var(--tw-sepia) var(--tw-drop-shadow)}:is(.dark .dark\:brightness-90){--tw-brightness:brightness(.9)}:is(.dark .dark\:brightness-95){--tw-brightness:brightness(.95)}:is(.dark .dark\:brightness-95),:is(.dark .dark\:brightness-\[0\.885\]){filter:var(--tw-blur) var(--tw-brightness) var(--tw-contrast) var(--tw-grayscale) var(--tw-hue-rotate) var(--tw-invert) var(--tw-saturate) var(--tw-sepia) var(--tw-drop-shadow)}:is(.dark .dark\:brightness-\[0\.885\]){--tw-brightness:brightness(0.885)}:is(.dark .dark\:after\:text-gray-500):after{content:var(--tw-content);--tw-text-opacity:1;color:rgb(173 181 189/var(--tw-text-opacity))}:is(.dark .dark\:checked\:border-primary:checked){--tw-border-opacity:1;border-color:rgb(11 85 119/var(--tw-border-opacity))}:is(.dark .dark\:checked\:bg-primary:checked){--tw-bg-opacity:1;background-color:rgb(11 85 119/var(--tw-bg-opacity))}:is(.dark .dark\:hover\:bg-primary\/20:hover){background-color:#0b557733}:is(.dark .dark\:hover\:bg-primary\/60:hover){background-color:#0b557799}:is(.dark .dark\:hover\:bg-slate-700\/50:hover){background-color:#34476780}:is(.dark .dark\:hover\:bg-slate-800:hover){--tw-bg-opacity:1;background-color:rgb(58 65 111/var(--tw-bg-opacity))}:is(.dark .dark\:hover\:brightness-100:hover){--tw-brightness:brightness(1)}:is(.dark .dark\:hover\:brightness-100:hover),:is(.dark .dark\:hover\:brightness-105:hover){filter:var(--tw-blur) var(--tw-brightness) var(--tw-contrast) var(--tw-grayscale) var(--tw-hue-rotate) var(--tw-invert) var(--tw-saturate) var(--tw-sepia) var(--tw-drop-shadow)}:is(.dark .dark\:hover\:brightness-105:hover){--tw-brightness:brightness(1.05)}:is(.dark .dark\:hover\:brightness-90:hover){--tw-brightness:brightness(.9);filter:var(--tw-blur) var(--tw-brightness) var(--tw-contrast) var(--tw-grayscale) var(--tw-hue-rotate) var(--tw-invert) var(--tw-saturate) var(--tw-sepia) var(--tw-drop-shadow)}:is(.dark .dark\:disabled\:border-gray-700\/0:disabled){border-color:#49505700}:is(.dark .dark\:disabled\:border-gray-800:disabled){--tw-border-opacity:1;border-color:rgb(37 47 64/var(--tw-border-opacity))}:is(.dark .dark\:disabled\:bg-gray-700:disabled){--tw-bg-opacity:1;background-color:rgb(73 80 87/var(--tw-bg-opacity))}:is(.dark .dark\:disabled\:bg-gray-800:disabled){--tw-bg-opacity:1;background-color:rgb(37 47 64/var(--tw-bg-opacity))}:is(.dark .dark\:disabled\:text-gray-300:disabled){--tw-text-opacity:1;color:rgb(210 214 218/var(--tw-text-opacity))}:is(.dark .dark\:disabled\:hover\:translate-y-0:hover:disabled){--tw-translate-y:0px;transform:translate(var(--tw-translate-x),var(--tw-translate-y)) rotate(var(--tw-rotate)) skewX(var(--tw-skew-x)) skewY(var(--tw-skew-y)) scaleX(var(--tw-scale-x)) scaleY(var(--tw-scale-y))}:is(.dark .dark\:disabled\:hover\:border-gray-700\/0:hover:disabled){border-color:#49505700}:is(.dark .dark\:disabled\:hover\:bg-gray-700:hover:disabled){--tw-bg-opacity:1;background-color:rgb(73 80 87/var(--tw-bg-opacity))}@media (min-width:576px){.sm\:right-24{right:6rem}.sm\:right-40{right:10rem}.sm\:right-6{right:1.5rem}.sm\:top-2{top:.5rem}.sm\:top-\[4\.5rem\]{top:4.5rem}.sm\:col-span-4{grid-column:span 4/span 4}.sm\:col-span-6{grid-column:span 6/span 6}.sm\:col-start-5{grid-column-start:5}.sm\:mx-4{margin-left:1rem;margin-right:1rem}.sm\:mx-6{margin-left:1.5rem;margin-right:1.5rem}.sm\:ml-1{margin-left:.25rem}.sm\:mr-16{margin-right:4rem}.sm\:inline{display:inline}.sm\:h-10{height:2.5rem}.sm\:h-14{height:3.5rem}.sm\:h-7{height:1.75rem}.sm\:max-h-125{max-height:31.25rem}.sm\:max-h-28{max-height:7rem}.sm\:w-36{width:9rem}.sm\:w-50{width:12.5rem}.sm\:w-7{width:1.75rem}.sm\:min-w-\[500px\]{min-width:500px}.sm\:scale-100{--tw-scale-x:1;--tw-scale-y:1;transform:translate(var(--tw-translate-x),var(--tw-translate-y)) rotate(var(--tw-rotate)) skewX(var(--tw-skew-x)) skewY(var(--tw-skew-y)) scaleX(var(--tw-scale-x)) scaleY(var(--tw-scale-y))}.sm\:flex-row{flex-direction:row}.sm\:items-center{align-items:center}.sm\:justify-end{justify-content:flex-end}.sm\:justify-items-start{justify-items:start}.sm\:gap-4{gap:1rem}.sm\:px-12{padding-left:3rem;padding-right:3rem}.sm\:px-4{padding-left:1rem;padding-right:1rem}.sm\:px-6{padding-left:1.5rem;padding-right:1.5rem}.sm\:py-0{padding-top:0;padding-bottom:0}.sm\:pt-6{padding-top:1.5rem}.sm\:text-left{text-align:left}}@media (min-width:768px){.md\:right-8{right:2rem}.md\:right-\[3\.75rem\]{right:3.75rem}.md\:top-\[40\%\]{top:40%}.md\:col-span-4{grid-column:span 4/span 4}.md\:col-span-5{grid-column:span 5/span 5}.md\:col-span-6{grid-column:span 6/span 6}.md\:col-span-7{grid-column:span 7/span 7}.md\:col-span-8{grid-column:span 8/span 8}.md\:mx-6{margin-left:1.5rem;margin-right:1.5rem}.md\:my-3{margin-top:.75rem;margin-bottom:.75rem}.md\:mb-0{margin-bottom:0}.md\:mb-3{margin-bottom:.75rem}.md\:mb-8{margin-bottom:2rem}.md\:mr-3{margin-right:.75rem}.md\:mt-0{margin-top:0}.md\:mt-6{margin-top:1.5rem}.md\:block{display:block}.md\:hidden{display:none}.md\:h-16{height:4rem}.md\:max-h-160{max-height:40rem}.md\:min-h-75-screen{min-height:75vh}.md\:w-1\/2{width:50%}.md\:w-60{width:15rem}.md\:max-w-\[600px\]{max-width:600px}.md\:justify-end{justify-content:flex-end}.md\:gap-x-6{-moz-column-gap:1.5rem;column-gap:1.5rem}.md\:px-3{padding-left:.75rem;padding-right:.75rem}.md\:px-4{padding-left:1rem;padding-right:1rem}.md\:px-6{padding-left:1.5rem;padding-right:1.5rem}.md\:py-2{padding-top:.5rem;padding-bottom:.5rem}.md\:py-4{padding-top:1rem;padding-bottom:1rem}.md\:text-base{font-size:1rem;line-height:1.5rem}}@media (min-width:992px){.lg\:relative{position:relative}.lg\:order-1{order:1}.lg\:order-2{order:2}.lg\:col-span-1{grid-column:span 1/span 1}.lg\:col-span-4{grid-column:span 4/span 4}.lg\:col-span-6{grid-column:span 6/span 6}.lg\:col-span-8{grid-column:span 8/span 8}.lg\:mx-0{margin-left:0;margin-right:0}.lg\:mx-8{margin-left:2rem;margin-right:2rem}.lg\:my-3{margin-top:.75rem;margin-bottom:.75rem}.lg\:mt-0{margin-top:0}.lg\:mt-4{margin-top:1rem}.lg\:block{display:block}.lg\:flex{display:flex}.lg\:hidden{display:none}.lg\:h-24{height:6rem}.lg\:h-9{height:2.25rem}.lg\:w-80{width:20rem}.lg\:w-9{width:2.25rem}.lg\:flex-row{flex-direction:row}.lg\:flex-nowrap{flex-wrap:nowrap}.lg\:justify-start{justify-content:flex-start}.lg\:justify-end{justify-content:flex-end}.lg\:justify-between{justify-content:space-between}.lg\:gap-6{gap:1.5rem}.lg\:gap-x-4{-moz-column-gap:1rem;column-gap:1rem}.lg\:bg-gray-50{--tw-bg-opacity:1;background-color:rgb(248 249 250/var(--tw-bg-opacity))}.lg\:px-6{padding-left:1.5rem;padding-right:1.5rem}.lg\:pb-1{padding-bottom:.25rem}.lg\:text-left{text-align:left}}@media (min-width:1200px){.xl\:left-0{left:0}.xl\:right-24{right:6rem}.xl\:right-6{right:1.5rem}.xl\:ml-6{margin-left:1.5rem}.xl\:ml-68{margin-left:17rem}.xl\:hidden{display:none}.xl\:translate-x-0{--tw-translate-x:0px;transform:translate(var(--tw-translate-x),var(--tw-translate-y)) rotate(var(--tw-rotate)) skewX(var(--tw-skew-x)) skewY(var(--tw-skew-y)) scaleX(var(--tw-scale-x)) scaleY(var(--tw-scale-y))}.xl\:p-1{padding:.25rem}.xl\:p-1\.5{padding:.375rem}.xl\:pl-75{padding-left:18.75rem}.xl\:text-base{font-size:1rem;line-height:1.5rem}}@media (min-width:1320px){.\32xl\:col-span-4{grid-column:span 4/span 4}.\32xl\:col-span-6{grid-column:span 6/span 6}.\32xl\:mx-6{margin-left:1.5rem;margin-right:1.5rem}.\32xl\:my-3{margin-top:.75rem;margin-bottom:.75rem}}@media (min-width:1920px){.\33xl\:col-span-3{grid-column:span 3/span 3}.\33xl\:col-span-4{grid-column:span 4/span 4}.\33xl\:col-span-5{grid-column:span 5/span 5}}@media (min-width:340px){.xs\:flex-row{flex-direction:row}.xs\:items-center{align-items:center}.xs\:justify-start{justify-content:flex-start}.xs\:pl-2{padding-left:.5rem}.xs\:text-sm{font-size:.875rem;line-height:1.5rem}}.\[\&\>\*\]\:bg-primary>*{--tw-bg-opacity:1;background-color:rgb(11 85 119/var(--tw-bg-opacity))}
\ No newline at end of file
diff --git a/src/ui/static/css/flatpickr.css b/src/ui/static/css/flatpickr.css
index 2d0f7af19..848f04384 100644
--- a/src/ui/static/css/flatpickr.css
+++ b/src/ui/static/css/flatpickr.css
@@ -1 +1 @@
-.flatpickr-calendar.noCalendar.hasTime .flatpickr-time,.numInputWrapper{height:auto}.flatpickr-calendar{background:0 0;opacity:0;display:none;text-align:center;visibility:hidden;padding:0;-webkit-animation:none;animation:none;direction:ltr;border:0;font-size:14px;line-height:24px;border-radius:5px;position:absolute;width:307.875px;-webkit-box-sizing:border-box;box-sizing:border-box;-ms-touch-action:manipulation;touch-action:manipulation;-webkit-box-shadow:0 3px 13px rgba(0,0,0,.08);box-shadow:0 3px 13px rgba(0,0,0,.08)}.flatpickr-wrapper,.numInputWrapper input,.numInputWrapper span{display:inline-block}.flatpickr-calendar.inline,.flatpickr-calendar.open{opacity:1;max-height:640px;visibility:visible}.flatpickr-calendar.open{display:inline-block;z-index:99999}.flatpickr-calendar.animate.open{-webkit-animation:.3s cubic-bezier(.23,1,.32,1) fpFadeInDown;animation:.3s cubic-bezier(.23,1,.32,1) fpFadeInDown}.flatpickr-calendar.inline{display:block;position:relative;top:2px}.flatpickr-calendar.static{position:absolute;top:calc(100% + 2px)}.flatpickr-calendar.static.open{z-index:999;display:block}.flatpickr-calendar.multiMonth .flatpickr-days .dayContainer:nth-child(n+1) .flatpickr-day.inRange:nth-child(7n+7){-webkit-box-shadow:none!important;box-shadow:none!important}.flatpickr-calendar.multiMonth .flatpickr-days .dayContainer:nth-child(n+2) .flatpickr-day.inRange:nth-child(7n+1){-webkit-box-shadow:-2px 0 0 #e6e6e6,5px 0 0 #e6e6e6;box-shadow:-2px 0 0 #e6e6e6,5px 0 0 #e6e6e6}.flatpickr-calendar .hasTime .dayContainer,.flatpickr-calendar .hasWeeks .dayContainer{border-bottom:0;border-bottom-right-radius:0;border-bottom-left-radius:0}.flatpickr-calendar .hasWeeks .dayContainer{border-left:0}.flatpickr-calendar.hasTime .flatpickr-innerContainer{border-bottom:0}.flatpickr-calendar.hasTime .flatpickr-time{height:40px;border-top:1px solid rgba(72,72,72,.2);border:1px solid rgba(72,72,72,.2)}.flatpickr-calendar:after,.flatpickr-calendar:before{position:absolute;display:block;pointer-events:none;border:solid transparent;content:"";height:0;width:0;left:22px}.flatpickr-months .flatpickr-next-month i,.flatpickr-months .flatpickr-prev-month i,.flatpickr-wrapper,.numInputWrapper{position:relative}.flatpickr-calendar.arrowRight:after,.flatpickr-calendar.arrowRight:before,.flatpickr-calendar.rightMost:after,.flatpickr-calendar.rightMost:before{left:auto;right:22px}.flatpickr-calendar.arrowCenter:after,.flatpickr-calendar.arrowCenter:before{left:50%;right:50%}.flatpickr-calendar:before{border-width:5px;margin:0 -5px}.flatpickr-calendar:after{border-width:4px;margin:0 -4px}.flatpickr-calendar.arrowTop:after,.flatpickr-calendar.arrowTop:before{bottom:100%}.flatpickr-calendar.arrowTop:before{border-bottom-color:rgba(72,72,72,.2)}.flatpickr-calendar.arrowTop:after{border-bottom-color:#085577}.flatpickr-calendar.arrowBottom:after,.flatpickr-calendar.arrowBottom:before{top:100%}.flatpickr-calendar.arrowBottom:before{border-top-color:rgba(72,72,72,.2)}.flatpickr-calendar.arrowBottom:after{border-top-color:#085577}.flatpickr-calendar:focus,.flatpickr-current-month .flatpickr-monthDropdown-months:active,.flatpickr-current-month .flatpickr-monthDropdown-months:focus,.flatpickr-current-month input.cur-year:focus,.flatpickr-days:focus{outline:0}.flatpickr-months,.flatpickr-weekdays{display:-webkit-box;display:-webkit-flex;display:-ms-flexbox}.flatpickr-months{display:flex}.flatpickr-months .flatpickr-month{border-radius:5px 5px 0 0;background:#085577;color:#fff;fill:#fff;height:34px;line-height:1;text-align:center;position:relative;-webkit-user-select:none;-moz-user-select:none;-ms-user-select:none;user-select:none;overflow:hidden;-webkit-box-flex:1;-webkit-flex:1;-ms-flex:1;flex:1}.flatpickr-months .flatpickr-next-month,.flatpickr-months .flatpickr-prev-month{-webkit-user-select:none;-moz-user-select:none;-ms-user-select:none;user-select:none;text-decoration:none;cursor:pointer;position:absolute;top:0;height:34px;padding:10px;z-index:3;color:#fff;fill:#fff}.flatpickr-months .flatpickr-next-month.flatpickr-disabled,.flatpickr-months .flatpickr-prev-month.flatpickr-disabled{display:none}.flatpickr-months .flatpickr-next-month.flatpickr-prev-month,.flatpickr-months .flatpickr-prev-month.flatpickr-prev-month{left:0}.flatpickr-months .flatpickr-next-month.flatpickr-next-month,.flatpickr-months .flatpickr-prev-month.flatpickr-next-month{right:0}.flatpickr-months .flatpickr-next-month:hover,.flatpickr-months .flatpickr-prev-month:hover{color:#bbb}.flatpickr-months .flatpickr-next-month:hover svg,.flatpickr-months .flatpickr-prev-month:hover svg{fill:#40bb6b}.flatpickr-months .flatpickr-next-month svg,.flatpickr-months .flatpickr-prev-month svg{width:14px;height:14px}.flatpickr-months .flatpickr-next-month svg path,.flatpickr-months .flatpickr-prev-month svg path{-webkit-transition:fill .1s;transition:fill .1s;fill:inherit}.numInputWrapper input{width:100%}.numInputWrapper input::-ms-clear{display:none}.numInputWrapper input::-webkit-inner-spin-button,.numInputWrapper input::-webkit-outer-spin-button{margin:0;-webkit-appearance:none}.numInputWrapper span{position:absolute;right:0;width:14px;padding:0 4px 0 2px;height:50%;line-height:50%;opacity:0;cursor:pointer;border:1px solid rgba(72,72,72,.15);-webkit-box-sizing:border-box;box-sizing:border-box}.numInputWrapper span:hover{background:rgba(0,0,0,.1)}.numInputWrapper span:active{background:rgba(0,0,0,.2)}.numInputWrapper span:after{display:block;content:"";position:absolute}.numInputWrapper span.arrowUp{top:0;border-bottom:0}.numInputWrapper span.arrowUp:after{border-left:4px solid transparent;border-right:4px solid transparent;border-bottom:4px solid rgba(72,72,72,.6);top:26%}.numInputWrapper span.arrowDown{top:50%}.numInputWrapper span.arrowDown:after{border-left:4px solid transparent;border-right:4px solid transparent;border-top:4px solid rgba(72,72,72,.6);top:40%}.numInputWrapper span svg{width:inherit;height:auto}.numInputWrapper span svg path{fill:rgba(255,255,255,0.5)}.flatpickr-current-month .flatpickr-monthDropdown-months:hover,.flatpickr-current-month span.cur-month:hover,.numInputWrapper:hover{background:rgba(0,0,0,.05)}.numInputWrapper:hover span{opacity:1}.flatpickr-current-month{font-size:135%;font-weight:300;color:inherit;position:absolute;width:75%;left:12.5%;padding:7.48px 0 0;line-height:1;height:34px;display:inline-block;text-align:center;-webkit-transform:translate3d(0,0,0);transform:translate3d(0,0,0)}.flatpickr-current-month span.cur-month{font-family:inherit;font-weight:700;color:inherit;display:inline-block;margin-left:.5ch;padding:0}.flatpickr-current-month .flatpickr-monthDropdown-months,.flatpickr-current-month input.cur-year{color:inherit;font-size:inherit;font-family:inherit;font-weight:300;height:auto;line-height:inherit;padding:0 0 0 .5ch;vertical-align:initial}.flatpickr-current-month .numInputWrapper{width:6ch;display:inline-block}.flatpickr-current-month .numInputWrapper span.arrowUp:after{border-bottom-color:#fff}.flatpickr-current-month .numInputWrapper span.arrowDown:after{border-top-color:#fff}.flatpickr-current-month input.cur-year{background:0 0;-webkit-box-sizing:border-box;box-sizing:border-box;cursor:text;margin:0;display:inline-block;border:0;border-radius:0;-webkit-appearance:textfield;-moz-appearance:textfield;appearance:textfield}.flatpickr-current-month input.cur-year[disabled],.flatpickr-current-month input.cur-year[disabled]:hover{font-size:100%;color:rgba(255,255,255,.5);background:0 0;pointer-events:none}.flatpickr-current-month .flatpickr-monthDropdown-months{appearance:menulist;background:#085577;border:none;border-radius:0;box-sizing:border-box;cursor:pointer;margin:-1px 0 0;outline:0;position:relative;-webkit-box-sizing:border-box;-webkit-appearance:menulist;-moz-appearance:menulist;width:auto}.flatpickr-current-month .flatpickr-monthDropdown-months .flatpickr-monthDropdown-month{background-color:#085577;outline:0;padding:0}.flatpickr-weekdays{background:#085577;text-align:center;overflow:hidden;width:100%;display:flex;-webkit-box-align:center;-webkit-align-items:center;-ms-flex-align:center;align-items:center;height:28px}.flatpickr-weekdays .flatpickr-weekdaycontainer{display:-webkit-box;display:-webkit-flex;display:-ms-flexbox;display:flex;-webkit-box-flex:1;-webkit-flex:1;-ms-flex:1;flex:1}span.flatpickr-weekday{cursor:default;font-size:90%;background:#085577;color:#fff;line-height:1;margin:0;text-align:center;display:block;-webkit-box-flex:1;-webkit-flex:1;-ms-flex:1;flex:1;font-weight:bolder}.dayContainer,.flatpickr-weeks{padding:1px 0 0}.flatpickr-days{position:relative;overflow:hidden;display:-webkit-box;display:-webkit-flex;display:-ms-flexbox;display:flex;-webkit-box-align:start;-webkit-align-items:flex-start;-ms-flex-align:start;align-items:flex-start;width:307.875px;border-left:1px solid rgba(72,72,72,.2);border-right:1px solid rgba(72,72,72,.2)}.dayContainer{padding:0;outline:0;text-align:left;width:307.875px;min-width:307.875px;max-width:307.875px;-webkit-box-sizing:border-box;box-sizing:border-box;display:inline-block;display:-ms-flexbox;display:-webkit-box;display:-webkit-flex;display:flex;-webkit-flex-wrap:wrap;flex-wrap:wrap;-ms-flex-wrap:wrap;-ms-flex-pack:justify;-webkit-justify-content:space-around;justify-content:space-around;-webkit-transform:translate3d(0,0,0);transform:translate3d(0,0,0);opacity:1}.dayContainer+.dayContainer{-webkit-box-shadow:-1px 0 0 rgba(72,72,72,.2);box-shadow:-1px 0 0 rgba(72,72,72,.2)}.flatpickr-day{background:0 0;border:1px solid transparent;border-radius:150px;-webkit-box-sizing:border-box;box-sizing:border-box;color:#484848;cursor:pointer;font-weight:400;width:14.2857143%;-webkit-flex-basis:14.2857143%;-ms-flex-preferred-size:14.2857143%;flex-basis:14.2857143%;max-width:39px;height:39px;line-height:39px;margin:0;display:inline-block;position:relative;-webkit-box-pack:center;-webkit-justify-content:center;-ms-flex-pack:center;justify-content:center;text-align:center}.flatpickr-day.inRange,.flatpickr-day.nextMonthDay.inRange,.flatpickr-day.nextMonthDay.today.inRange,.flatpickr-day.nextMonthDay:focus,.flatpickr-day.nextMonthDay:hover,.flatpickr-day.prevMonthDay.inRange,.flatpickr-day.prevMonthDay.today.inRange,.flatpickr-day.prevMonthDay:focus,.flatpickr-day.prevMonthDay:hover,.flatpickr-day.today.inRange,.flatpickr-day:focus,.flatpickr-day:hover{cursor:pointer;outline:0;background:#e2e2e2;border-color:#e2e2e2}.flatpickr-day.today{border-color:#bbb}.flatpickr-day.today:focus,.flatpickr-day.today:hover{border-color:#bbb;background:#bbb;color:#fff}.flatpickr-day.endRange,.flatpickr-day.endRange.inRange,.flatpickr-day.endRange.nextMonthDay,.flatpickr-day.endRange.prevMonthDay,.flatpickr-day.endRange:focus,.flatpickr-day.endRange:hover,.flatpickr-day.selected,.flatpickr-day.selected.inRange,.flatpickr-day.selected.nextMonthDay,.flatpickr-day.selected.prevMonthDay,.flatpickr-day.selected:focus,.flatpickr-day.selected:hover,.flatpickr-day.startRange,.flatpickr-day.startRange.inRange,.flatpickr-day.startRange.nextMonthDay,.flatpickr-day.startRange.prevMonthDay,.flatpickr-day.startRange:focus,.flatpickr-day.startRange:hover{background:#40bb6b;-webkit-box-shadow:none;box-shadow:none;color:#fff;border-color:#40bb6b}.flatpickr-day.endRange.startRange,.flatpickr-day.selected.startRange,.flatpickr-day.startRange.startRange{border-radius:50px 0 0 50px}.flatpickr-day.endRange.endRange,.flatpickr-day.selected.endRange,.flatpickr-day.startRange.endRange{border-radius:0 50px 50px 0}.flatpickr-day.endRange.startRange+.endRange:not(:nth-child(7n + 1)),.flatpickr-day.selected.startRange+.endRange:not(:nth-child(7n + 1)),.flatpickr-day.startRange.startRange+.endRange:not(:nth-child(7n + 1)){-webkit-box-shadow:-10px 0 0 #085577;box-shadow:-10px 0 0 #085577}.flatpickr-day.endRange.startRange.endRange,.flatpickr-day.selected.startRange.endRange,.flatpickr-day.startRange.startRange.endRange{border-radius:50px}.flatpickr-day.inRange{border-radius:0;-webkit-box-shadow:-5px 0 0 #e2e2e2,5px 0 0 #e2e2e2;box-shadow:-5px 0 0 #e2e2e2,5px 0 0 #e2e2e2}.flatpickr-day.flatpickr-disabled,.flatpickr-day.flatpickr-disabled:hover,.flatpickr-day.nextMonthDay,.flatpickr-day.notAllowed,.flatpickr-day.notAllowed.nextMonthDay,.flatpickr-day.notAllowed.prevMonthDay,.flatpickr-day.prevMonthDay{color:rgba(72,72,72,.3);background:0 0;border-color:transparent;cursor:default}.flatpickr-day.flatpickr-disabled,.flatpickr-day.flatpickr-disabled:hover{cursor:not-allowed;color:rgba(72,72,72,.1)}.flatpickr-day.week.selected{border-radius:0;-webkit-box-shadow:-5px 0 0 #085577,5px 0 0 #085577;box-shadow:-5px 0 0 #085577,5px 0 0 #085577}.flatpickr-day.hidden{visibility:hidden}.rangeMode .flatpickr-day{margin-top:1px}.flatpickr-weekwrapper{float:left}.flatpickr-weekwrapper .flatpickr-weeks{padding:0 12px;border-left:1px solid rgba(72,72,72,.2)}.flatpickr-weekwrapper .flatpickr-weekday{float:none;width:100%;line-height:28px}.flatpickr-weekwrapper span.flatpickr-day,.flatpickr-weekwrapper span.flatpickr-day:hover{display:block;width:100%;max-width:none;color:rgba(72,72,72,.3);background:0 0;cursor:default;border:none}.flatpickr-innerContainer{display:block;display:-webkit-box;display:-webkit-flex;display:-ms-flexbox;display:flex;-webkit-box-sizing:border-box;box-sizing:border-box;overflow:hidden;background:#fff;border-bottom:1px solid rgba(72,72,72,.2)}.flatpickr-rContainer{display:inline-block;padding:0;-webkit-box-sizing:border-box;box-sizing:border-box}.flatpickr-time{text-align:center;outline:0;display:block;height:0;line-height:40px;max-height:40px;-webkit-box-sizing:border-box;box-sizing:border-box;overflow:hidden;display:-webkit-box;display:-webkit-flex;display:-ms-flexbox;display:flex;background:#fff;border-radius:0 0 5px 5px}.flatpickr-time:after{content:"";display:table;clear:both}.flatpickr-time .numInputWrapper{-webkit-box-flex:1;-webkit-flex:1;-ms-flex:1;flex:1;width:40%;height:40px;float:left}.flatpickr-time .numInputWrapper span.arrowUp:after{border-bottom-color:#484848}.flatpickr-time .numInputWrapper span.arrowDown:after{border-top-color:#484848}.flatpickr-time.hasSeconds .numInputWrapper{width:26%}.flatpickr-time.time24hr .numInputWrapper{width:49%}.flatpickr-time input{background:0 0;-webkit-box-shadow:none;box-shadow:none;border:0;border-radius:0;text-align:center;margin:0;padding:0;height:inherit;line-height:inherit;color:#484848;font-size:14px;position:relative;-webkit-box-sizing:border-box;box-sizing:border-box;-webkit-appearance:textfield;-moz-appearance:textfield;appearance:textfield}.flatpickr-time input.flatpickr-hour{font-weight:700}.flatpickr-time input.flatpickr-minute,.flatpickr-time input.flatpickr-second{font-weight:400}.flatpickr-time input:focus{outline:0;border:0}.flatpickr-time .flatpickr-am-pm,.flatpickr-time .flatpickr-time-separator{height:inherit;float:left;line-height:inherit;color:#484848;font-weight:700;width:2%;-webkit-user-select:none;-moz-user-select:none;-ms-user-select:none;user-select:none;-webkit-align-self:center;-ms-flex-item-align:center;align-self:center}.flatpickr-time .flatpickr-am-pm{outline:0;width:18%;cursor:pointer;text-align:center;font-weight:400}.flatpickr-time .flatpickr-am-pm:focus,.flatpickr-time .flatpickr-am-pm:hover,.flatpickr-time input:focus,.flatpickr-time input:hover{background:#eaeaea}.flatpickr-input[readonly]{cursor:pointer}@-webkit-keyframes fpFadeInDown{from{opacity:0;-webkit-transform:translate3d(0,-20px,0);transform:translate3d(0,-20px,0)}to{opacity:1;-webkit-transform:translate3d(0,0,0);transform:translate3d(0,0,0)}}@keyframes fpFadeInDown{from{opacity:0;-webkit-transform:translate3d(0,-20px,0);transform:translate3d(0,-20px,0)}to{opacity:1;-webkit-transform:translate3d(0,0,0);transform:translate3d(0,0,0)}}
+.flatpickr-calendar{background:0 0;opacity:0;display:none;text-align:center;visibility:hidden;padding:0;-webkit-animation:none;animation:none;direction:ltr;border:0;font-size:14px;line-height:24px;border-radius:5px;position:absolute;width:307.875px;-webkit-box-sizing:border-box;box-sizing:border-box;-ms-touch-action:manipulation;touch-action:manipulation;-webkit-box-shadow:0 3px 13px rgba(0,0,0,.08);box-shadow:0 3px 13px rgba(0,0,0,.08)}.flatpickr-wrapper,.numInputWrapper input,.numInputWrapper span{display:inline-block}.flatpickr-calendar.inline,.flatpickr-calendar.open{opacity:1;max-height:640px;visibility:visible}.flatpickr-calendar.open{display:inline-block;z-index:99999}.flatpickr-calendar.animate.open{-webkit-animation:.3s cubic-bezier(.23,1,.32,1) fpFadeInDown;animation:.3s cubic-bezier(.23,1,.32,1) fpFadeInDown}.flatpickr-calendar.inline{display:block;position:relative;top:2px}.flatpickr-calendar.static{position:absolute;top:calc(100% + 2px)}.flatpickr-calendar.static.open{z-index:999;display:block}.flatpickr-calendar.multiMonth .flatpickr-days .dayContainer:nth-child(n+1) .flatpickr-day.inRange:nth-child(7n+7){-webkit-box-shadow:none!important;box-shadow:none!important}.flatpickr-calendar.multiMonth .flatpickr-days .dayContainer:nth-child(n+2) .flatpickr-day.inRange:nth-child(7n+1){-webkit-box-shadow:-2px 0 0 #e6e6e6,5px 0 0 #e6e6e6;box-shadow:-2px 0 0 #e6e6e6,5px 0 0 #e6e6e6}.flatpickr-calendar .hasTime .dayContainer,.flatpickr-calendar .hasWeeks .dayContainer{border-bottom:0;border-bottom-right-radius:0;border-bottom-left-radius:0}.flatpickr-calendar .hasWeeks .dayContainer{border-left:0}.flatpickr-calendar.hasTime .flatpickr-innerContainer{border-bottom:0}.flatpickr-calendar.hasTime .flatpickr-time{height:40px;border-top:1px solid rgba(72,72,72,.2);border:1px solid rgba(72,72,72,.2)}.flatpickr-calendar.noCalendar.hasTime .flatpickr-time{height:auto}.flatpickr-calendar:after,.flatpickr-calendar:before{position:absolute;display:block;pointer-events:none;border:solid transparent;content:"";height:0;width:0;left:22px}.flatpickr-months .flatpickr-next-month i,.flatpickr-months .flatpickr-prev-month i,.flatpickr-wrapper,.numInputWrapper{position:relative}.flatpickr-calendar.arrowRight:after,.flatpickr-calendar.arrowRight:before,.flatpickr-calendar.rightMost:after,.flatpickr-calendar.rightMost:before{left:auto;right:22px}.flatpickr-calendar.arrowCenter:after,.flatpickr-calendar.arrowCenter:before{left:50%;right:50%}.flatpickr-calendar:before{border-width:5px;margin:0 -5px}.flatpickr-calendar:after{border-width:4px;margin:0 -4px}.flatpickr-calendar.arrowTop:after,.flatpickr-calendar.arrowTop:before{bottom:100%}.flatpickr-calendar.arrowTop:before{border-bottom-color:rgba(72,72,72,.2)}.flatpickr-calendar.arrowTop:after{border-bottom-color:#085577}.flatpickr-calendar.arrowBottom:after,.flatpickr-calendar.arrowBottom:before{top:100%}.flatpickr-calendar.arrowBottom:before{border-top-color:rgba(72,72,72,.2)}.flatpickr-calendar.arrowBottom:after{border-top-color:#085577}.flatpickr-calendar:focus,.flatpickr-current-month .flatpickr-monthDropdown-months:active,.flatpickr-current-month .flatpickr-monthDropdown-months:focus,.flatpickr-current-month input.cur-year:focus,.flatpickr-days:focus{outline:0}.flatpickr-months,.flatpickr-weekdays{display:-webkit-box;display:-webkit-flex;display:-ms-flexbox}.flatpickr-months{display:flex}.flatpickr-months .flatpickr-month{border-radius:5px 5px 0 0;background:#085577;color:#fff;fill:#fff;height:34px;line-height:1;text-align:center;position:relative;-webkit-user-select:none;-moz-user-select:none;-ms-user-select:none;user-select:none;overflow:hidden;-webkit-box-flex:1;-webkit-flex:1;-ms-flex:1;flex:1}.flatpickr-months .flatpickr-next-month,.flatpickr-months .flatpickr-prev-month{-webkit-user-select:none;-moz-user-select:none;-ms-user-select:none;user-select:none;text-decoration:none;cursor:pointer;position:absolute;top:-3px;height:34px;padding:10px;z-index:3;color:#fff;fill:#fff}.flatpickr-months .flatpickr-next-month.flatpickr-disabled,.flatpickr-months .flatpickr-prev-month.flatpickr-disabled{display:none}.flatpickr-months .flatpickr-next-month.flatpickr-prev-month,.flatpickr-months .flatpickr-prev-month.flatpickr-prev-month{left:0}.flatpickr-months .flatpickr-next-month.flatpickr-next-month,.flatpickr-months .flatpickr-prev-month.flatpickr-next-month{right:0}.flatpickr-months .flatpickr-next-month:hover,.flatpickr-months .flatpickr-prev-month:hover{color:#bbb}.flatpickr-months .flatpickr-next-month:hover svg,.flatpickr-months .flatpickr-prev-month:hover svg{fill:#40bb6b}.flatpickr-months .flatpickr-next-month svg,.flatpickr-months .flatpickr-prev-month svg{width:14px;height:14px}.flatpickr-months .flatpickr-next-month svg path,.flatpickr-months .flatpickr-prev-month svg path{-webkit-transition:fill .1s;transition:fill .1s;fill:inherit}.numInputWrapper{height:auto;margin-left:12px}.numInputWrapper input{width:100%}.numInputWrapper input::-ms-clear{display:none}.numInputWrapper input::-webkit-inner-spin-button,.numInputWrapper input::-webkit-outer-spin-button{margin:0;-webkit-appearance:none}.numInputWrapper span{position:absolute;right:0;width:14px;padding:0 4px 0 2px;height:50%;line-height:50%;opacity:0;cursor:pointer;border-right:1px solid rgba(72,72,72,.15);-webkit-box-sizing:border-box;box-sizing:border-box;opacity:1}.numInputWrapper span:hover{background:rgba(0,0,0,.1)}.numInputWrapper span:active{background:rgba(0,0,0,.2)}.numInputWrapper span:after{display:block;content:"";position:absolute}.numInputWrapper span.arrowUp{top:0;border-bottom:0}.numInputWrapper span.arrowUp:after{border-left:4px solid transparent;border-right:4px solid transparent;border-bottom:4px solid rgba(72,72,72,.6);top:26%}.numInputWrapper span.arrowDown{top:50%}.numInputWrapper span.arrowDown:after{border-left:4px solid transparent;border-right:4px solid transparent;border-top:4px solid rgba(72,72,72,.6);top:40%}.numInputWrapper span svg{width:inherit;height:auto}.numInputWrapper span svg path{fill:rgba(255,255,255,0.5)}.flatpickr-current-month .flatpickr-monthDropdown-months:hover,.flatpickr-current-month span.cur-month:hover,.numInputWrapper:hover{background:rgba(0,0,0,.05)}.flatpickr-current-month{font-size:16px;font-weight:300;color:inherit;position:absolute;width:75%;left:12.5%;padding:7.48px 0 0;line-height:1;height:34px;display:inline-block;text-align:center;-webkit-transform:translate3d(0,0,0);transform:translate3d(0,0,0)}.flatpickr-current-month span.cur-month{font-family:inherit;font-weight:700;color:inherit;display:inline-block;margin-left:.5ch;padding:0}.flatpickr-current-month .flatpickr-monthDropdown-months,.flatpickr-current-month input.cur-year{color:inherit;font-size:inherit;font-family:inherit;font-weight:300;height:auto;line-height:inherit;vertical-align:initial}.flatpickr-current-month .numInputWrapper{width:6ch;display:inline-block}.flatpickr-current-month .numInputWrapper span.arrowUp:after{border-bottom-color:#fff}.flatpickr-current-month .numInputWrapper span.arrowDown:after{border-top-color:#fff}.flatpickr-current-month input.cur-year{background:0 0;-webkit-box-sizing:border-box;box-sizing:border-box;cursor:text;margin:0;padding-right:4px;display:inline-block;border:0;border-radius:0;-webkit-appearance:textfield;-moz-appearance:textfield;appearance:textfield}.flatpickr-current-month input.cur-year[disabled],.flatpickr-current-month input.cur-year[disabled]:hover{font-size:100%;color:rgba(255,255,255,.5);background:0 0;pointer-events:none}.flatpickr-current-month .flatpickr-monthDropdown-months{appearance:menulist;background:#085577;border:none;border-radius:0;box-sizing:border-box;cursor:pointer;margin:-1px 0 0;outline:0;padding:0 0 0 .5ch;position:relative;-webkit-box-sizing:border-box;-webkit-appearance:menulist;-moz-appearance:menulist;width:auto}.flatpickr-current-month .flatpickr-monthDropdown-months .flatpickr-monthDropdown-month{background-color:#085577;border-color:#085577;outline:0;padding:0;border-radius:4px;appearance:none}.flatpickr-weekdays{background:#085577;text-align:center;overflow:hidden;width:100%;display:flex;-webkit-box-align:center;-webkit-align-items:center;-ms-flex-align:center;align-items:center;height:28px}.flatpickr-weekdays .flatpickr-weekdaycontainer{display:-webkit-box;display:-webkit-flex;display:-ms-flexbox;display:flex;-webkit-box-flex:1;-webkit-flex:1;-ms-flex:1;flex:1}span.flatpickr-weekday{cursor:default;font-size:90%;background:#085577;color:#fff;line-height:1;margin:0;text-align:center;display:block;-webkit-box-flex:1;-webkit-flex:1;-ms-flex:1;flex:1;font-weight:bolder}.dayContainer,.flatpickr-weeks{padding:1px 0 0}.flatpickr-days{position:relative;overflow:hidden;display:-webkit-box;display:-webkit-flex;display:-ms-flexbox;display:flex;-webkit-box-align:start;-webkit-align-items:flex-start;-ms-flex-align:start;align-items:flex-start;width:307.875px;border-left:1px solid rgba(72,72,72,.2);border-right:1px solid rgba(72,72,72,.2)}.dayContainer{padding:4px;outline:0;text-align:left;width:307.875px;min-width:307.875px;max-width:307.875px;-webkit-box-sizing:border-box;box-sizing:border-box;display:inline-block;display:-ms-flexbox;display:-webkit-box;display:-webkit-flex;display:flex;-webkit-flex-wrap:wrap;flex-wrap:wrap;-ms-flex-wrap:wrap;-ms-flex-pack:justify;-webkit-justify-content:space-around;justify-content:space-around;-webkit-transform:translate3d(0,0,0);transform:translate3d(0,0,0);opacity:1}.dayContainer+.dayContainer{-webkit-box-shadow:-1px 0 0 rgba(72,72,72,.2);box-shadow:-1px 0 0 rgba(72,72,72,.2)}.flatpickr-day{background:0 0;border:1px solid transparent;border-radius:150px;-webkit-box-sizing:border-box;box-sizing:border-box;color:#484848;cursor:pointer;font-weight:400;width:14.2857143%;-webkit-flex-basis:14.2857143%;-ms-flex-preferred-size:14.2857143%;flex-basis:14.2857143%;max-width:39px;height:39px;line-height:39px;margin:1.5px;display:inline-block;position:relative;-webkit-box-pack:center;-webkit-justify-content:center;-ms-flex-pack:center;justify-content:center;text-align:center}.flatpickr-day.inRange,.flatpickr-day.nextMonthDay.inRange,.flatpickr-day.nextMonthDay.today.inRange,.flatpickr-day.nextMonthDay:focus,.flatpickr-day.nextMonthDay:hover,.flatpickr-day.prevMonthDay.inRange,.flatpickr-day.prevMonthDay.today.inRange,.flatpickr-day.prevMonthDay:focus,.flatpickr-day.prevMonthDay:hover,.flatpickr-day.today.inRange,.flatpickr-day:focus,.flatpickr-day:hover{cursor:pointer;outline:0;background:rgba(64,187,107);border-color:rgba(64,187,107);color:#fff}.flatpickr-day.today{border-color:rgba(64,187,107,.8)}.flatpickr-day.today:focus,.flatpickr-day.today:hover{border-color:rgba(64,187,107,.8);background:rgba(64,187,107,.8);color:#fff}.flatpickr-day.endRange,.flatpickr-day.endRange.inRange,.flatpickr-day.endRange.nextMonthDay,.flatpickr-day.endRange.prevMonthDay,.flatpickr-day.endRange:focus,.flatpickr-day.endRange:hover,.flatpickr-day.selected,.flatpickr-day.selected.inRange,.flatpickr-day.selected.nextMonthDay,.flatpickr-day.selected.prevMonthDay,.flatpickr-day.selected:focus,.flatpickr-day.selected:hover,.flatpickr-day.startRange,.flatpickr-day.startRange.inRange,.flatpickr-day.startRange.nextMonthDay,.flatpickr-day.startRange.prevMonthDay,.flatpickr-day.startRange:focus,.flatpickr-day.startRange:hover{background:#40bb6b;-webkit-box-shadow:none;box-shadow:none;color:#fff;border-color:#40bb6b}.flatpickr-day.endRange.startRange,.flatpickr-day.selected.startRange,.flatpickr-day.startRange.startRange{border-radius:50px 0 0 50px}.flatpickr-day.endRange.endRange,.flatpickr-day.selected.endRange,.flatpickr-day.startRange.endRange{border-radius:0 50px 50px 0}.flatpickr-day.endRange.startRange+.endRange:not(:nth-child(7n + 1)),.flatpickr-day.selected.startRange+.endRange:not(:nth-child(7n + 1)),.flatpickr-day.startRange.startRange+.endRange:not(:nth-child(7n + 1)){-webkit-box-shadow:-10px 0 0 #085577;box-shadow:-10px 0 0 #085577}.flatpickr-day.endRange.startRange.endRange,.flatpickr-day.selected.startRange.endRange,.flatpickr-day.startRange.startRange.endRange{border-radius:50px}.flatpickr-day.inRange{border-radius:0;-webkit-box-shadow:-5px 0 0 #e2e2e2,5px 0 0 #e2e2e2;box-shadow:-5px 0 0 #e2e2e2,5px 0 0 #e2e2e2}.flatpickr-day.flatpickr-disabled,.flatpickr-day.flatpickr-disabled:hover,.flatpickr-day.nextMonthDay,.flatpickr-day.notAllowed,.flatpickr-day.notAllowed.nextMonthDay,.flatpickr-day.notAllowed.prevMonthDay,.flatpickr-day.prevMonthDay{color:rgba(72,72,72,.5);background:0 0;border-color:transparent;cursor:default}.flatpickr-day.flatpickr-disabled,.flatpickr-day.flatpickr-disabled:hover{cursor:not-allowed;color:rgba(72,72,72,.1)}.flatpickr-day.week.selected{border-radius:0;-webkit-box-shadow:-5px 0 0 #085577,5px 0 0 #085577;box-shadow:-5px 0 0 #085577,5px 0 0 #085577}.flatpickr-day.hidden{visibility:hidden}.rangeMode .flatpickr-day{margin-top:1px}.flatpickr-weekwrapper{float:left}.flatpickr-weekwrapper .flatpickr-weeks{padding:0 12px;border-left:1px solid rgba(72,72,72,.2)}.flatpickr-weekwrapper .flatpickr-weekday{float:none;width:100%;line-height:28px}.flatpickr-weekwrapper span.flatpickr-day,.flatpickr-weekwrapper span.flatpickr-day:hover{display:block;width:100%;max-width:none;color:rgba(72,72,72,.3);background:0 0;cursor:default;border:none}.flatpickr-innerContainer{display:block;display:-webkit-box;display:-webkit-flex;display:-ms-flexbox;display:flex;-webkit-box-sizing:border-box;box-sizing:border-box;overflow:hidden;background:#fff;border-bottom:1px solid rgba(72,72,72,.2)}.flatpickr-rContainer{display:inline-block;padding:0;-webkit-box-sizing:border-box;box-sizing:border-box}.flatpickr-time{text-align:center;outline:0;display:block;height:0;line-height:40px;max-height:40px;-webkit-box-sizing:border-box;box-sizing:border-box;overflow:hidden;display:-webkit-box;display:-webkit-flex;display:-ms-flexbox;display:flex;background:#fff;border-radius:0 0 5px 5px}.flatpickr-time:after{content:"";display:table;clear:both}.flatpickr-time .numInputWrapper{-webkit-box-flex:1;-webkit-flex:1;-ms-flex:1;flex:1;width:40%;height:40px;float:left}.flatpickr-time .numInputWrapper span.arrowUp:after{border-bottom-color:#484848}.flatpickr-time .numInputWrapper span.arrowDown:after{border-top-color:#484848}.flatpickr-time.hasSeconds .numInputWrapper{width:26%}.flatpickr-time.time24hr .numInputWrapper{width:49%}.flatpickr-time input{background:0 0;-webkit-box-shadow:none;box-shadow:none;border:0;border-radius:0;text-align:center;margin:0;padding:0;height:inherit;line-height:inherit;color:#484848;font-size:14px;position:relative;-webkit-box-sizing:border-box;box-sizing:border-box;-webkit-appearance:textfield;-moz-appearance:textfield;appearance:textfield}.flatpickr-time input.flatpickr-hour{font-weight:700}.flatpickr-time input.flatpickr-minute,.flatpickr-time input.flatpickr-second{font-weight:400}.flatpickr-time input:focus{outline:0;border:0}.flatpickr-time-separator{margin-left:8px;font-size:16px}.flatpickr-time .flatpickr-am-pm,.flatpickr-time .flatpickr-time-separator{height:inherit;float:left;line-height:inherit;color:#484848;font-weight:700;width:2%;-webkit-user-select:none;-moz-user-select:none;-ms-user-select:none;user-select:none;-webkit-align-self:center;-ms-flex-item-align:center;align-self:center}.flatpickr-time .flatpickr-am-pm{outline:0;width:18%;cursor:pointer;text-align:center;font-weight:400}.flatpickr-time .flatpickr-am-pm:focus,.flatpickr-time .flatpickr-am-pm:hover,.flatpickr-time input:focus,.flatpickr-time input:hover{background:#eaeaea}.flatpickr-input[readonly]{cursor:pointer}@-webkit-keyframes fpFadeInDown{from{opacity:0;-webkit-transform:translate3d(0,-20px,0);transform:translate3d(0,-20px,0)}to{opacity:1;-webkit-transform:translate3d(0,0,0);transform:translate3d(0,0,0)}}@keyframes fpFadeInDown{from{opacity:0;-webkit-transform:translate3d(0,-20px,0);transform:translate3d(0,-20px,0)}to{opacity:1;-webkit-transform:translate3d(0,0,0);transform:translate3d(0,0,0)}}
diff --git a/src/ui/static/css/flatpickr.dark.css b/src/ui/static/css/flatpickr.dark.css
index 8e93dd540..b686b8b5f 100644
--- a/src/ui/static/css/flatpickr.dark.css
+++ b/src/ui/static/css/flatpickr.dark.css
@@ -1 +1 @@
-.dark .flatpickr-calendar{background:#3f4458;opacity:0;display:none;text-align:center;visibility:hidden;padding:0;-webkit-animation:none;animation:none;direction:ltr;border:0;font-size:14px;line-height:24px;border-radius:5px;position:absolute;width:307.875px;-webkit-box-sizing:border-box;box-sizing:border-box;-ms-touch-action:manipulation;touch-action:manipulation;-webkit-box-shadow:1px 0 0 #20222c,-1px 0 0 #20222c,0 1px 0 #20222c,0 -1px 0 #20222c,0 3px 13px rgba(0,0,0,.08);box-shadow:1px 0 0 #20222c,-1px 0 0 #20222c,0 1px 0 #20222c,0 -1px 0 #20222c,0 3px 13px rgba(0,0,0,.08)}.dark .flatpickr-calendar.inline,.dark .flatpickr-calendar.open{opacity:1;max-height:640px;visibility:visible}.dark .flatpickr-calendar.open{display:inline-block;z-index:99999}.dark .flatpickr-calendar.animate.open{-webkit-animation:.3s cubic-bezier(.23,1,.32,1) fpFadeInDown;animation:.3s cubic-bezier(.23,1,.32,1) fpFadeInDown}.dark .flatpickr-calendar.inline{display:block;position:relative;top:2px}.dark .flatpickr-calendar.static{position:absolute;top:calc(100% + 2px)}.dark .flatpickr-calendar.static.open{z-index:999;display:block}.dark .flatpickr-calendar.multiMonth .flatpickr-days .dayContainer:nth-child(n+1) .flatpickr-day.inRange:nth-child(7n+7){-webkit-box-shadow:none!important;box-shadow:none!important}.dark .flatpickr-calendar.multiMonth .flatpickr-days .dayContainer:nth-child(n+2) .flatpickr-day.inRange:nth-child(7n+1){-webkit-box-shadow:-2px 0 0 #e6e6e6,5px 0 0 #e6e6e6;box-shadow:-2px 0 0 #e6e6e6,5px 0 0 #e6e6e6}.dark .flatpickr-calendar .hasTime .dayContainer,.dark .flatpickr-calendar .hasWeeks .dayContainer{border-bottom:0;border-bottom-right-radius:0;border-bottom-left-radius:0}.dark .flatpickr-calendar .hasWeeks .dayContainer{border-left:0}.dark .flatpickr-calendar.hasTime .flatpickr-time{height:40px;border-top:1px solid #20222c}.dark .flatpickr-calendar.noCalendar.hasTime .flatpickr-time{height:auto}.dark .flatpickr-calendar:after,.dark .flatpickr-calendar:before{position:absolute;display:block;pointer-events:none;border:solid transparent;content:"";height:0;width:0;left:22px}.dark .flatpickr-calendar.arrowRight:after,.dark .flatpickr-calendar.arrowRight:before,.dark .flatpickr-calendar.rightMost:after,.dark .flatpickr-calendar.rightMost:before{left:auto;right:22px}.dark .flatpickr-calendar.arrowCenter:after,.dark .flatpickr-calendar.arrowCenter:before{left:50%;right:50%}.dark .flatpickr-calendar:before{border-width:5px;margin:0 -5px}.dark .flatpickr-calendar:after{border-width:4px;margin:0 -4px}.dark .flatpickr-calendar.arrowTop:after,.dark .flatpickr-calendar.arrowTop:before{bottom:100%}.dark .flatpickr-calendar.arrowTop:before{border-bottom-color:#20222c}.dark .flatpickr-calendar.arrowTop:after{border-bottom-color:#3f4458}.dark .flatpickr-calendar.arrowBottom:after,.dark .flatpickr-calendar.arrowBottom:before{top:100%}.dark .flatpickr-calendar.arrowBottom:before{border-top-color:#20222c}.dark .flatpickr-calendar.arrowBottom:after{border-top-color:#3f4458}.dark .flatpickr-calendar:focus,.dark .flatpickr-current-month .flatpickr-monthDropdown-months:active,.dark .flatpickr-current-month .flatpickr-monthDropdown-months:focus,.dark .flatpickr-current-month input.cur-year:focus,.dark .flatpickr-days:focus{outline:0}.dark .flatpickr-wrapper{position:relative;display:inline-block}.dark .flatpickr-months,.dark .flatpickr-weekdays{display:-webkit-box;display:-webkit-flex;display:-ms-flexbox}.dark .flatpickr-months{display:flex}.dark .flatpickr-months .flatpickr-month{background:#085577;color:#fff;fill:#fff;height:34px;line-height:1;text-align:center;position:relative;-webkit-user-select:none;-moz-user-select:none;-ms-user-select:none;user-select:none;overflow:hidden;-webkit-box-flex:1;-webkit-flex:1;-ms-flex:1;flex:1}.dark .flatpickr-months .flatpickr-next-month,.dark .flatpickr-months .flatpickr-prev-month{-webkit-user-select:none;-moz-user-select:none;-ms-user-select:none;user-select:none;text-decoration:none;cursor:pointer;position:absolute;top:0;height:34px;padding:10px;z-index:3;color:#fff;fill:#fff}.dark .flatpickr-months .flatpickr-next-month.flatpickr-disabled,.dark .flatpickr-months .flatpickr-prev-month.flatpickr-disabled{display:none}.dark .flatpickr-months .flatpickr-next-month i,.dark .flatpickr-months .flatpickr-prev-month i{position:relative}.dark .flatpickr-months .flatpickr-next-month.flatpickr-prev-month,.dark .flatpickr-months .flatpickr-prev-month.flatpickr-prev-month{left:0}.dark .flatpickr-months .flatpickr-next-month.flatpickr-next-month,.dark .flatpickr-months .flatpickr-prev-month.flatpickr-next-month{right:0}.dark .flatpickr-months .flatpickr-next-month:hover,.dark .flatpickr-months .flatpickr-prev-month:hover{color:#eee}.dark .flatpickr-months .flatpickr-prev-month:hover svg,.dark.flatpickr-months .flatpickr-next-month:hover svg{fill:#40bb6b}.dark .flatpickr-months .flatpickr-next-month svg,.dark .flatpickr-months .flatpickr-prev-month svg{width:14px;height:14px}.dark .flatpickr-months .flatpickr-next-month svg path,.dark .flatpickr-months .flatpickr-prev-month svg path{-webkit-transition:fill .1s;transition:fill .1s;fill:inherit}.dark .numInputWrapper{position:relative;height:auto}.dark .numInputWrapper input,.dark .numInputWrapper span{display:inline-block}.dark .numInputWrapper input{width:100%}.dark .numInputWrapper input::-ms-clear{display:none}.dark .numInputWrapper input::-webkit-inner-spin-button,.dark .numInputWrapper input::-webkit-outer-spin-button{margin:0;-webkit-appearance:none}.dark .numInputWrapper span{position:absolute;right:0;width:14px;padding:0 4px 0 2px;height:50%;line-height:50%;opacity:0;cursor:pointer;border:1px solid rgba(255,255,255,.15);-webkit-box-sizing:border-box;box-sizing:border-box}.dark .numInputWrapper span:hover{background:rgba(192,187,167,.1)}.dark .numInputWrapper span:active{background:rgba(192,187,167,.2)}.dark .numInputWrapper span:after{display:block;content:"";position:absolute}.dark .numInputWrapper span.arrowUp{top:0;border-bottom:0}.dark .numInputWrapper span.arrowUp:after{border-left:4px solid transparent;border-right:4px solid transparent;border-bottom:4px solid rgba(255,255,255,.6);top:26%}.dark .numInputWrapper span.arrowDown{top:50%}.dark .numInputWrapper span.arrowDown:after{border-left:4px solid transparent;border-right:4px solid transparent;border-top:4px solid rgba(255,255,255,.6);top:40%}.dark .numInputWrapper span svg{width:inherit;height:auto}.dark .numInputWrapper span svg path{fill:rgba(255,255,255,0.5)}.dark .flatpickr-current-month .flatpickr-monthDropdown-months:hover,.dark .flatpickr-current-month span.cur-month:hover,.dark .numInputWrapper:hover{background:rgba(192,187,167,.05)}.dark .numInputWrapper:hover span{opacity:1}.dark .flatpickr-current-month{font-size:135%;font-weight:300;color:inherit;position:absolute;width:75%;left:12.5%;padding:7.48px 0 0;line-height:1;height:34px;display:inline-block;text-align:center;-webkit-transform:translate3d(0,0,0);transform:translate3d(0,0,0)}.dark .flatpickr-current-month span.cur-month{font-family:inherit;font-weight:700;color:inherit;display:inline-block;margin-left:.5ch;padding:0}.dark .flatpickr-current-month .flatpickr-monthDropdown-months,.dark .flatpickr-current-month input.cur-year{color:inherit;font-size:inherit;font-family:inherit;font-weight:300;height:auto;line-height:inherit;padding:0 0 0 .5ch;vertical-align:initial}.dark .flatpickr-current-month .numInputWrapper{width:6ch;display:inline-block}.dark .flatpickr-current-month .numInputWrapper span.arrowUp:after{border-bottom-color:#fff}.dark .flatpickr-current-month .numInputWrapper span.arrowDown:after{border-top-color:#fff}.dark .flatpickr-current-month input.cur-year{background:0 0;-webkit-box-sizing:border-box;box-sizing:border-box;cursor:text;margin:0;display:inline-block;border:0;border-radius:0;-webkit-appearance:textfield;-moz-appearance:textfield;appearance:textfield}.dark .flatpickr-current-month input.cur-year[disabled],.dark .flatpickr-current-month input.cur-year[disabled]:hover{font-size:100%;color:rgba(255,255,255,.5);background:0 0;pointer-events:none}.dark .flatpickr-current-month .flatpickr-monthDropdown-months{appearance:menulist;background:#085577;border:none;border-radius:0;box-sizing:border-box;cursor:pointer;margin:-1px 0 0;outline:0;position:relative;-webkit-box-sizing:border-box;-webkit-appearance:menulist;-moz-appearance:menulist;width:auto}.dark .flatpickr-current-month .flatpickr-monthDropdown-months .flatpickr-monthDropdown-month{background-color:#085577;outline:0;padding:0}.dark .flatpickr-weekdays{background:#085577;text-align:center;overflow:hidden;width:100%;display:flex;-webkit-box-align:center;-webkit-align-items:center;-ms-flex-align:center;align-items:center;height:28px}.dark .flatpickr-weekdays .flatpickr-weekdaycontainer{display:-webkit-box;display:-webkit-flex;display:-ms-flexbox;display:flex;-webkit-box-flex:1;-webkit-flex:1;-ms-flex:1;flex:1}.dark span.flatpickr-weekday{cursor:default;font-size:90%;background:#085577;color:#fff;line-height:1;margin:0;text-align:center;display:block;-webkit-box-flex:1;-webkit-flex:1;-ms-flex:1;flex:1;font-weight:bolder}.dark .dayContainer,.flatpickr-weeks{padding:1px 0 0}.dark .flatpickr-days{position:relative;overflow:hidden;display:-webkit-box;display:-webkit-flex;display:-ms-flexbox;display:flex;-webkit-box-align:start;-webkit-align-items:flex-start;-ms-flex-align:start;align-items:flex-start;width:307.875px;border:none}.dark .dayContainer{background:#1e3969;padding:0;outline:0;text-align:left;width:307.875px;min-width:307.875px;max-width:307.875px;-webkit-box-sizing:border-box;box-sizing:border-box;display:inline-block;display:-ms-flexbox;display:-webkit-box;display:-webkit-flex;display:flex;-webkit-flex-wrap:wrap;flex-wrap:wrap;-ms-flex-wrap:wrap;-ms-flex-pack:justify;-webkit-justify-content:space-around;justify-content:space-around;-webkit-transform:translate3d(0,0,0);transform:translate3d(0,0,0);opacity:1}.dark .dayContainer+.dark .dayContainer{-webkit-box-shadow:-1px 0 0 #20222c;box-shadow:-1px 0 0 #20222c}.dark .flatpickr-day{background:0 0;border:1px solid transparent;border-radius:150px;-webkit-box-sizing:border-box;box-sizing:border-box;color:rgba(255,255,255,.95);cursor:pointer;font-weight:400;width:14.2857143%;-webkit-flex-basis:14.2857143%;-ms-flex-preferred-size:14.2857143%;flex-basis:14.2857143%;max-width:39px;height:39px;line-height:39px;margin:0;display:inline-block;position:relative;-webkit-box-pack:center;-webkit-justify-content:center;-ms-flex-pack:center;justify-content:center;text-align:center}.dark .flatpickr-day.inRange,.dark .flatpickr-day.nextMonthDay.inRange,.dark .flatpickr-day.nextMonthDay.today.inRange,.dark .flatpickr-day.nextMonthDay:focus,.dark .flatpickr-day.nextMonthDay:hover,.dark .flatpickr-day.prevMonthDay.inRange,.dark .flatpickr-day.prevMonthDay.today.inRange,.dark .flatpickr-day.prevMonthDay:focus,.dark .flatpickr-day.prevMonthDay:hover,.dark .flatpickr-day.today.inRange,.dark .flatpickr-day:focus,.dark .flatpickr-day:hover{cursor:pointer;outline:0;background:#646c8c;border-color:#646c8c}.dark .flatpickr-day.today{border-color:#eee}.dark .flatpickr-day.today:focus,.dark .flatpickr-day.today:hover{border-color:#eee;background:#eee;color:#3f4458}.dark .flatpickr-day.endRange,.dark .flatpickr-day.endRange.inRange,.dark .flatpickr-day.endRange.nextMonthDay,.dark .flatpickr-day.endRange.prevMonthDay,.dark .flatpickr-day.endRange:focus,.dark .flatpickr-day.endRange:hover,.dark .flatpickr-day.selected,.dark .flatpickr-day.selected.inRange,.dark .flatpickr-day.selected.nextMonthDay,.dark .flatpickr-day.selected.prevMonthDay,.dark .flatpickr-day.selected:focus,.dark .flatpickr-day.selected:hover,.dark .flatpickr-day.startRange,.dark .flatpickr-day.startRange.inRange,.dark .flatpickr-day.startRange.nextMonthDay,.dark .flatpickr-day.startRange.prevMonthDay,.dark .flatpickr-day.startRange:focus,.dark .flatpickr-day.startRange:hover{background:#40bb6b;-webkit-box-shadow:none;box-shadow:none;color:#fff;border-color:#40bb6b}.dark .flatpickr-day.endRange.startRange,.dark .flatpickr-day.selected.startRange,.dark .flatpickr-day.startRange.startRange{border-radius:50px 0 0 50px}.dark .flatpickr-day.endRange.endRange,.dark .flatpickr-day.selected.endRange,.dark .flatpickr-day.startRange.endRange{border-radius:0 50px 50px 0}.dark .flatpickr-day.endRange.startRange+.endRange:not(:nth-child(7n + 1)),.dark .flatpickr-day.selected.startRange+.endRange:not(:nth-child(7n + 1)),.dark .flatpickr-day.startRange.startRange+.endRange:not(:nth-child(7n + 1)){-webkit-box-shadow:-10px 0 0 #80cbc4;box-shadow:-10px 0 0 #80cbc4}.dark .flatpickr-day.endRange.startRange.endRange,.dark .flatpickr-day.selected.startRange.endRange,.dark .flatpickr-day.startRange.startRange.endRange{border-radius:50px}.dark .flatpickr-day.inRange{border-radius:0;-webkit-box-shadow:-5px 0 0 #646c8c,5px 0 0 #646c8c;box-shadow:-5px 0 0 #646c8c,5px 0 0 #646c8c}.dark .flatpickr-day.flatpickr-disabled,.dark .flatpickr-day.flatpickr-disabled:hover,.dark .flatpickr-day.nextMonthDay,.dark .flatpickr-day.notAllowed,.dark .flatpickr-day.notAllowed.nextMonthDay,.dark .flatpickr-day.notAllowed.prevMonthDay,.dark .flatpickr-day.prevMonthDay{color:rgba(255,255,255,.3);background:0 0;border-color:transparent;cursor:default}.dark .flatpickr-day.flatpickr-disabled,.dark .flatpickr-day.flatpickr-disabled:hover{cursor:not-allowed;color:rgba(255,255,255,.1)}.dark .flatpickr-day.week.selected{border-radius:0;-webkit-box-shadow:-5px 0 0 #80cbc4,5px 0 0 #80cbc4;box-shadow:-5px 0 0 #80cbc4,5px 0 0 #80cbc4}.dark .flatpickr-day.hidden{visibility:hidden}.dark .rangeMode .flatpickr-day{margin-top:1px}.dark .flatpickr-weekwrapper{float:left}.dark .flatpickr-weekwrapper .flatpickr-weeks{padding:0 12px;-webkit-box-shadow:1px 0 0 #20222c;box-shadow:1px 0 0 #20222c}.dark .flatpickr-weekwrapper .flatpickr-weekday{float:none;width:100%;line-height:28px}.dark .flatpickr-weekwrapper span.flatpickr-day,.dark .flatpickr-weekwrapper span.flatpickr-day:hover{display:block;width:100%;max-width:none;color:rgba(255,255,255,.3);background:0 0;cursor:default;border:none}.dark .flatpickr-innerContainer{display:block;display:-webkit-box;display:-webkit-flex;display:-ms-flexbox;display:flex;-webkit-box-sizing:border-box;box-sizing:border-box;overflow:hidden;border-bottom:none}.dark .flatpickr-rContainer{display:inline-block;padding:0;-webkit-box-sizing:border-box;box-sizing:border-box}.dark .flatpickr-time{text-align:center;outline:0;display:block;height:0;line-height:40px;max-height:40px;-webkit-box-sizing:border-box;box-sizing:border-box;overflow:hidden;display:-webkit-box;display:-webkit-flex;display:-ms-flexbox;display:flex}.dark .flatpickr-time:after{content:"";display:table;clear:both}.dark .flatpickr-time .numInputWrapper{-webkit-box-flex:1;-webkit-flex:1;-ms-flex:1;flex:1;width:40%;height:40px;float:left}.dark .flatpickr-time .numInputWrapper span.arrowUp:after{border-bottom-color:rgba(255,255,255,.95)}.dark .flatpickr-time .numInputWrapper span.arrowDown:after{border-top-color:rgba(255,255,255,.95)}.dark .flatpickr-time.hasSeconds .numInputWrapper{width:26%}.dark .flatpickr-time.time24hr .numInputWrapper{width:49%}.dark .flatpickr-time input{background:0 0;-webkit-box-shadow:none;box-shadow:none;border:0;border-radius:0;text-align:center;margin:0;padding:0;height:inherit;line-height:inherit;color:rgba(255,255,255,.95);font-size:14px;position:relative;-webkit-box-sizing:border-box;box-sizing:border-box;-webkit-appearance:textfield;-moz-appearance:textfield;appearance:textfield}.dark .flatpickr-time input.flatpickr-hour{font-weight:700}.dark .flatpickr-time input.flatpickr-minute,.dark .flatpickr-time input.flatpickr-second{font-weight:400}.dark .flatpickr-time input:focus{outline:0;border:0}.dark .flatpickr-time .flatpickr-am-pm,.dark .flatpickr-time .flatpickr-time-separator{height:inherit;float:left;line-height:inherit;color:rgba(255,255,255,.95);font-weight:700;width:2%;-webkit-user-select:none;-moz-user-select:none;-ms-user-select:none;user-select:none;-webkit-align-self:center;-ms-flex-item-align:center;align-self:center}.dark .flatpickr-time .flatpickr-am-pm{outline:0;width:18%;cursor:pointer;text-align:center;font-weight:400}.dark .flatpickr-time .flatpickr-am-pm:focus,.dark .flatpickr-time .flatpickr-am-pm:hover,.dark .flatpickr-time input:focus,.dark .flatpickr-time input:hover{background:#6a7395}.dark .flatpickr-input[readonly]{cursor:pointer}@-webkit-keyframes fpFadeInDown{from{opacity:0;-webkit-transform:translate3d(0,-20px,0);transform:translate3d(0,-20px,0)}to{opacity:1;-webkit-transform:translate3d(0,0,0);transform:translate3d(0,0,0)}}@keyframes fpFadeInDown{from{opacity:0;-webkit-transform:translate3d(0,-20px,0);transform:translate3d(0,-20px,0)}to{opacity:1;-webkit-transform:translate3d(0,0,0);transform:translate3d(0,0,0)}}
+.dark .flatpickr-calendar{background:#3f4458;opacity:0;display:none;text-align:center;visibility:hidden;padding:0;-webkit-animation:none;animation:none;direction:ltr;border:0;font-size:14px;line-height:24px;border-radius:5px;position:absolute;width:307.875px;-webkit-box-sizing:border-box;box-sizing:border-box;-ms-touch-action:manipulation;touch-action:manipulation;-webkit-box-shadow:1px 0 0 #20222c,-1px 0 0 #20222c,0 1px 0 #20222c,0 -1px 0 #20222c,0 3px 13px rgba(0,0,0,.08);box-shadow:1px 0 0 #20222c,-1px 0 0 #20222c,0 1px 0 #20222c,0 -1px 0 #20222c,0 3px 13px rgba(0,0,0,.08)}.dark .flatpickr-calendar.inline,.dark .flatpickr-calendar.open{opacity:1;max-height:640px;visibility:visible}.dark .flatpickr-calendar.open{display:inline-block;z-index:99999}.dark .flatpickr-calendar.animate.open{-webkit-animation:.3s cubic-bezier(.23,1,.32,1) fpFadeInDown;animation:.3s cubic-bezier(.23,1,.32,1) fpFadeInDown}.dark .flatpickr-calendar.inline{display:block;position:relative;top:2px}.dark .flatpickr-calendar.static{position:absolute;top:calc(100% + 2px)}.dark .flatpickr-calendar.static.open{z-index:999;display:block}.dark .flatpickr-calendar.multiMonth .flatpickr-days .dayContainer:nth-child(n+1) .flatpickr-day.inRange:nth-child(7n+7){-webkit-box-shadow:none!important;box-shadow:none!important}.dark .flatpickr-calendar.multiMonth .flatpickr-days .dayContainer:nth-child(n+2) .flatpickr-day.inRange:nth-child(7n+1){-webkit-box-shadow:-2px 0 0 #e6e6e6,5px 0 0 #e6e6e6;box-shadow:-2px 0 0 #e6e6e6,5px 0 0 #e6e6e6}.dark .flatpickr-calendar .hasTime .dayContainer,.dark .flatpickr-calendar .hasWeeks .dayContainer{border-bottom:0;border-bottom-right-radius:0;border-bottom-left-radius:0}.dark .flatpickr-calendar .hasWeeks .dayContainer{border-left:0}.dark .flatpickr-calendar.hasTime .flatpickr-time{height:40px;border-top:1px solid #20222c;background-color:#1e3969}.dark .flatpickr-calendar.noCalendar.hasTime .flatpickr-time{height:auto}.dark .flatpickr-calendar:after,.dark .flatpickr-calendar:before{position:absolute;display:block;pointer-events:none;border:solid transparent;content:"";height:0;width:0;left:22px}.dark .flatpickr-calendar.arrowRight:after,.dark .flatpickr-calendar.arrowRight:before,.dark .flatpickr-calendar.rightMost:after,.dark .flatpickr-calendar.rightMost:before{left:auto;right:22px}.dark .flatpickr-calendar.arrowCenter:after,.dark .flatpickr-calendar.arrowCenter:before{left:50%;right:50%}.dark .flatpickr-calendar:before{border-width:5px;margin:0 -5px}.dark .flatpickr-calendar:after{border-width:4px;margin:0 -4px}.dark .flatpickr-calendar.arrowTop:after,.dark .flatpickr-calendar.arrowTop:before{bottom:100%}.dark .flatpickr-calendar.arrowTop:before{border-bottom-color:#20222c}.dark .flatpickr-calendar.arrowTop:after{border-bottom-color:#3f4458}.dark .flatpickr-calendar.arrowBottom:after,.dark .flatpickr-calendar.arrowBottom:before{top:100%}.dark .flatpickr-calendar.arrowBottom:before{border-top-color:#20222c}.dark .flatpickr-calendar.arrowBottom:after{border-top-color:#3f4458}.dark .flatpickr-calendar:focus,.dark .flatpickr-current-month .flatpickr-monthDropdown-months:active,.dark .flatpickr-current-month .flatpickr-monthDropdown-months:focus,.dark .flatpickr-current-month input.cur-year:focus,.dark .flatpickr-days:focus{outline:0}.dark .flatpickr-wrapper{position:relative;display:inline-block}.dark .flatpickr-months,.dark .flatpickr-weekdays{display:-webkit-box;display:-webkit-flex;display:-ms-flexbox}.dark .flatpickr-months{display:flex}.dark .flatpickr-months .flatpickr-month{background:#085577;color:#fff;fill:#fff;height:34px;line-height:1;text-align:center;position:relative;-webkit-user-select:none;-moz-user-select:none;-ms-user-select:none;user-select:none;overflow:hidden;-webkit-box-flex:1;-webkit-flex:1;-ms-flex:1;flex:1}.dark .flatpickr-months .flatpickr-next-month,.dark .flatpickr-months .flatpickr-prev-month{-webkit-user-select:none;-moz-user-select:none;-ms-user-select:none;user-select:none;text-decoration:none;cursor:pointer;position:absolute;top:-3px;height:34px;padding:10px;z-index:3;color:#fff;fill:#fff}.dark .flatpickr-months .flatpickr-next-month.flatpickr-disabled,.dark .flatpickr-months .flatpickr-prev-month.flatpickr-disabled{display:none}.dark .flatpickr-months .flatpickr-next-month i,.dark .flatpickr-months .flatpickr-prev-month i{position:relative}.dark .flatpickr-months .flatpickr-next-month.flatpickr-prev-month,.dark .flatpickr-months .flatpickr-prev-month.flatpickr-prev-month{left:0}.dark .flatpickr-months .flatpickr-next-month.flatpickr-next-month,.dark .flatpickr-months .flatpickr-prev-month.flatpickr-next-month{right:0}.dark .flatpickr-months .flatpickr-next-month:hover,.dark .flatpickr-months .flatpickr-prev-month:hover{color:#eee}.dark .flatpickr-months .flatpickr-prev-month:hover svg,.dark.flatpickr-months .flatpickr-next-month:hover svg{fill:#40bb6b}.dark .flatpickr-months .flatpickr-next-month svg,.dark .flatpickr-months .flatpickr-prev-month svg{width:14px;height:14px}.dark .flatpickr-months .flatpickr-next-month svg path,.dark .flatpickr-months .flatpickr-prev-month svg path{-webkit-transition:fill .1s;transition:fill .1s;fill:inherit}.dark .numInputWrapper{position:relative;height:auto;margin-left:12px}.dark .numInputWrapper input,.dark .numInputWrapper span{display:inline-block}.dark .numInputWrapper input{width:100%}.dark .numInputWrapper input::-ms-clear{display:none}.dark .numInputWrapper input::-webkit-inner-spin-button,.dark .numInputWrapper input::-webkit-outer-spin-button{margin:0;-webkit-appearance:none}.dark .flatpickr-current-month .numInputWrapper span{border:0}.dark .numInputWrapper span{position:absolute;right:0;width:14px;padding:0 4px 0 2px;height:50%;line-height:50%;opacity:0;cursor:pointer;border-right:1px solid rgba(26,25,25,.4);-webkit-box-sizing:border-box;box-sizing:border-box;opacity:1}.dark .numInputWrapper span:hover{background:rgba(192,187,167,.1)}.dark .numInputWrapper span:active{background:rgba(192,187,167,.2)}.dark .numInputWrapper span:after{display:block;content:"";position:absolute}.dark .numInputWrapper span.arrowUp{top:0;border-bottom:0}.dark .numInputWrapper span.arrowUp:after{border-left:4px solid transparent;border-right:4px solid transparent;border-bottom:4px solid rgba(255,255,255,.6);top:26%}.dark .numInputWrapper span.arrowDown{top:50%}.dark .numInputWrapper span.arrowDown:after{border-left:4px solid transparent;border-right:4px solid transparent;border-top:4px solid rgba(255,255,255,.6);top:40%}.dark .numInputWrapper span svg{width:inherit;height:auto}.dark .numInputWrapper span svg path{fill:rgba(255,255,255,0.5)}.dark .flatpickr-current-month .flatpickr-monthDropdown-months:hover,.dark .flatpickr-current-month span.cur-month:hover,.dark .numInputWrapper:hover{background:rgba(192,187,167,.05)}.dark .flatpickr-current-month{font-size:16px;font-weight:300;color:inherit;position:absolute;width:75%;left:12.5%;padding:7.48px 0 0;line-height:1;height:34px;display:inline-block;text-align:center;-webkit-transform:translate3d(0,0,0);transform:translate3d(0,0,0)}.dark .flatpickr-current-month span.cur-month{font-family:inherit;font-weight:700;color:inherit;display:inline-block;margin-left:.5ch;padding:0}.dark .flatpickr-current-month .flatpickr-monthDropdown-months,.dark .flatpickr-current-month input.cur-year{color:inherit;font-size:inherit;font-family:inherit;font-weight:300;height:auto;line-height:inherit;vertical-align:initial}.dark .flatpickr-current-month .numInputWrapper{width:6ch;display:inline-block}.dark .flatpickr-current-month .numInputWrapper span.arrowUp:after{border-bottom-color:#fff}.dark .flatpickr-current-month .numInputWrapper span.arrowDown:after{border-top-color:#fff}.dark .flatpickr-current-month input.cur-year{background:0 0;-webkit-box-sizing:border-box;box-sizing:border-box;cursor:text;padding-right:4px;margin:0;display:inline-block;border:0;border-radius:0;-webkit-appearance:textfield;-moz-appearance:textfield;appearance:textfield}.dark .flatpickr-current-month input.cur-year[disabled],.dark .flatpickr-current-month input.cur-year[disabled]:hover{font-size:100%;color:rgba(255,255,255,.5);background:0 0;pointer-events:none}.dark .flatpickr-current-month .flatpickr-monthDropdown-months{appearance:menulist;background:#085577;border:none;border-radius:0;box-sizing:border-box;cursor:pointer;margin:-1px 0 0;outline:0;padding:0 0 0 .5ch;position:relative;-webkit-box-sizing:border-box;-webkit-appearance:menulist;-moz-appearance:menulist;width:auto}.dark .flatpickr-current-month .flatpickr-monthDropdown-months .flatpickr-monthDropdown-month{background-color:#085577;outline:0;padding:0}.dark .flatpickr-weekdays{background:#085577;text-align:center;overflow:hidden;width:100%;display:flex;-webkit-box-align:center;-webkit-align-items:center;-ms-flex-align:center;align-items:center;height:28px}.dark .flatpickr-weekdays .flatpickr-weekdaycontainer{display:-webkit-box;display:-webkit-flex;display:-ms-flexbox;display:flex;-webkit-box-flex:1;-webkit-flex:1;-ms-flex:1;flex:1}.dark span.flatpickr-weekday{cursor:default;font-size:90%;background:#085577;color:#fff;line-height:1;margin:0;text-align:center;display:block;-webkit-box-flex:1;-webkit-flex:1;-ms-flex:1;flex:1;font-weight:bolder}.dark .dayContainer,.flatpickr-weeks{padding:1px 0 0}.dark .flatpickr-days{position:relative;overflow:hidden;display:-webkit-box;display:-webkit-flex;display:-ms-flexbox;display:flex;-webkit-box-align:start;-webkit-align-items:flex-start;-ms-flex-align:start;align-items:flex-start;width:307.875px;border:none}.dark .dayContainer{background:#1e3969;padding:3px;outline:0;text-align:left;width:307.875px;min-width:307.875px;max-width:307.875px;-webkit-box-sizing:border-box;box-sizing:border-box;display:inline-block;display:-ms-flexbox;display:-webkit-box;display:-webkit-flex;display:flex;-webkit-flex-wrap:wrap;flex-wrap:wrap;-ms-flex-wrap:wrap;-ms-flex-pack:justify;-webkit-justify-content:space-around;justify-content:space-around;-webkit-transform:translate3d(0,0,0);transform:translate3d(0,0,0);opacity:1}.dark .dayContainer+.dark .dayContainer{-webkit-box-shadow:-1px 0 0 #20222c;box-shadow:-1px 0 0 #20222c}.dark .flatpickr-day{background:0 0;border:1px solid transparent;border-radius:150px;-webkit-box-sizing:border-box;box-sizing:border-box;color:rgba(255,255,255,.95);cursor:pointer;font-weight:400;width:14.2857143%;-webkit-flex-basis:14.2857143%;-ms-flex-preferred-size:14.2857143%;flex-basis:14.2857143%;max-width:39px;height:39px;line-height:39px;margin:1.5px;display:inline-block;position:relative;-webkit-box-pack:center;-webkit-justify-content:center;-ms-flex-pack:center;justify-content:center;text-align:center}.dark .flatpickr-day.inRange,.dark .flatpickr-day.nextMonthDay.inRange,.dark .flatpickr-day.nextMonthDay.today.inRange,.dark .flatpickr-day.nextMonthDay:focus,.dark .flatpickr-day.nextMonthDay:hover,.dark .flatpickr-day.prevMonthDay.inRange,.dark .flatpickr-day.prevMonthDay.today.inRange,.dark .flatpickr-day.prevMonthDay:focus,.dark .flatpickr-day.prevMonthDay:hover,.dark .flatpickr-day.today.inRange,.dark .flatpickr-day:focus,.dark .flatpickr-day:hover{cursor:pointer;outline:0;background:rgba(64,187,107);border-color:rgba(64,187,107);color:#fff}.dark .flatpickr-day.today{border-color:rgba(64,187,107,.8)}.dark .flatpickr-day.today:focus,.dark .flatpickr-day.today:hover{border-color:rgba(64,187,107,.8);background:rgba(64,187,107,.8);color:#fff}.dark .flatpickr-day.endRange,.dark .flatpickr-day.endRange.inRange,.dark .flatpickr-day.endRange.nextMonthDay,.dark .flatpickr-day.endRange.prevMonthDay,.dark .flatpickr-day.endRange:focus,.dark .flatpickr-day.endRange:hover,.dark .flatpickr-day.selected,.dark .flatpickr-day.selected.inRange,.dark .flatpickr-day.selected.nextMonthDay,.dark .flatpickr-day.selected.prevMonthDay,.dark .flatpickr-day.selected:focus,.dark .flatpickr-day.selected:hover,.dark .flatpickr-day.startRange,.dark .flatpickr-day.startRange.inRange,.dark .flatpickr-day.startRange.nextMonthDay,.dark .flatpickr-day.startRange.prevMonthDay,.dark .flatpickr-day.startRange:focus,.dark .flatpickr-day.startRange:hover{background:#40bb6b;-webkit-box-shadow:none;box-shadow:none;color:#fff;border-color:#40bb6b}.dark .flatpickr-day.endRange.startRange,.dark .flatpickr-day.selected.startRange,.dark .flatpickr-day.startRange.startRange{border-radius:50px 0 0 50px}.dark .flatpickr-day.endRange.endRange,.dark .flatpickr-day.selected.endRange,.dark .flatpickr-day.startRange.endRange{border-radius:0 50px 50px 0}.dark .flatpickr-day.endRange.startRange+.endRange:not(:nth-child(7n + 1)),.dark .flatpickr-day.selected.startRange+.endRange:not(:nth-child(7n + 1)),.dark .flatpickr-day.startRange.startRange+.endRange:not(:nth-child(7n + 1)){-webkit-box-shadow:-10px 0 0 #80cbc4;box-shadow:-10px 0 0 #80cbc4}.dark .flatpickr-day.endRange.startRange.endRange,.dark .flatpickr-day.selected.startRange.endRange,.dark .flatpickr-day.startRange.startRange.endRange{border-radius:50px}.dark .flatpickr-day.inRange{border-radius:0;-webkit-box-shadow:-5px 0 0 #646c8c,5px 0 0 #646c8c;box-shadow:-5px 0 0 #646c8c,5px 0 0 #646c8c}.dark .flatpickr-day.flatpickr-disabled,.dark .flatpickr-day.flatpickr-disabled:hover,.dark .flatpickr-day.nextMonthDay,.dark .flatpickr-day.notAllowed,.dark .flatpickr-day.notAllowed.nextMonthDay,.dark .flatpickr-day.notAllowed.prevMonthDay,.dark .flatpickr-day.prevMonthDay{color:rgba(255,255,255,.5);background:0 0;border-color:transparent;cursor:default}.dark .flatpickr-day.flatpickr-disabled,.dark .flatpickr-day.flatpickr-disabled:hover{cursor:not-allowed;color:rgba(255,255,255,.1)}.dark .flatpickr-day.week.selected{border-radius:0;-webkit-box-shadow:-5px 0 0 #80cbc4,5px 0 0 #80cbc4;box-shadow:-5px 0 0 #80cbc4,5px 0 0 #80cbc4}.dark .flatpickr-day.hidden{visibility:hidden}.dark .rangeMode .flatpickr-day{margin-top:1px}.dark .flatpickr-weekwrapper{float:left}.dark .flatpickr-weekwrapper .flatpickr-weeks{padding:0 12px;-webkit-box-shadow:1px 0 0 #20222c;box-shadow:1px 0 0 #20222c}.dark .flatpickr-weekwrapper .flatpickr-weekday{float:none;width:100%;line-height:28px}.dark .flatpickr-weekwrapper span.flatpickr-day,.dark .flatpickr-weekwrapper span.flatpickr-day:hover{display:block;width:100%;max-width:none;color:rgba(255,255,255,.3);background:0 0;cursor:default;border:none}.dark .flatpickr-innerContainer{display:block;display:-webkit-box;display:-webkit-flex;display:-ms-flexbox;display:flex;-webkit-box-sizing:border-box;box-sizing:border-box;overflow:hidden;border-bottom:none}.dark .flatpickr-rContainer{display:inline-block;padding:0;-webkit-box-sizing:border-box;box-sizing:border-box}.dark .flatpickr-time{text-align:center;outline:0;display:block;height:0;line-height:40px;max-height:40px;-webkit-box-sizing:border-box;box-sizing:border-box;overflow:hidden;display:-webkit-box;display:-webkit-flex;display:-ms-flexbox;display:flex}.dark .flatpickr-time:after{content:"";display:table;clear:both}.dark .flatpickr-time .numInputWrapper{-webkit-box-flex:1;-webkit-flex:1;-ms-flex:1;flex:1;width:40%;height:40px;float:left}.dark .flatpickr-time .numInputWrapper span.arrowUp:after{border-bottom-color:rgba(255,255,255,.95)}.dark .flatpickr-time .numInputWrapper span.arrowDown:after{border-top-color:rgba(255,255,255,.95)}.dark .flatpickr-time.hasSeconds .numInputWrapper{width:26%}.dark .flatpickr-time.time24hr .numInputWrapper{width:49%}.dark .flatpickr-time input{background:0 0;-webkit-box-shadow:none;box-shadow:none;border:0;border-radius:0;text-align:center;margin:0;padding:0;height:inherit;line-height:inherit;color:rgba(255,255,255,.95);font-size:14px;position:relative;-webkit-box-sizing:border-box;box-sizing:border-box;-webkit-appearance:textfield;-moz-appearance:textfield;appearance:textfield}.dark .flatpickr-time input.flatpickr-hour{font-weight:700}.dark .flatpickr-time input.flatpickr-minute,.dark .flatpickr-time input.flatpickr-second{font-weight:400}.dark .flatpickr-time input:focus{outline:0;border:0}.dark .flatpickr-time .flatpickr-am-pm,.dark .flatpickr-time .flatpickr-time-separator{height:inherit;float:left;line-height:inherit;color:rgba(255,255,255,.95);font-weight:700;width:2%;-webkit-user-select:none;-moz-user-select:none;-ms-user-select:none;user-select:none;-webkit-align-self:center;-ms-flex-item-align:center;align-self:center}.dark .flatpickr-time .flatpickr-am-pm{outline:0;width:18%;cursor:pointer;text-align:center;font-weight:400}.dark .flatpickr-time .flatpickr-am-pm:focus,.dark .flatpickr-time .flatpickr-am-pm:hover,.dark .flatpickr-time input:focus,.dark .flatpickr-time input:hover{background:rgba(64,187,107,.8)}.dark .flatpickr-input[readonly]{cursor:pointer}@-webkit-keyframes fpFadeInDown{from{opacity:0;-webkit-transform:translate3d(0,-20px,0);transform:translate3d(0,-20px,0)}to{opacity:1;-webkit-transform:translate3d(0,0,0);transform:translate3d(0,0,0)}}@keyframes fpFadeInDown{from{opacity:0;-webkit-transform:translate3d(0,-20px,0);transform:translate3d(0,-20px,0)}to{opacity:1;-webkit-transform:translate3d(0,0,0);transform:translate3d(0,0,0)}}
diff --git a/src/ui/static/js/account.js b/src/ui/static/js/account.js
index 6d2463a4d..c0aa1ee36 100644
--- a/src/ui/static/js/account.js
+++ b/src/ui/static/js/account.js
@@ -45,7 +45,7 @@ class SubmitAccount {
"focus:valid:!ring-red-500",
"active:!border-red-500",
"active:valid:!border-red-500",
- "valid:!border-red-500"
+ "valid:!border-red-500",
);
this.pwAlertEl.classList.add("opacity-0");
this.pwAlertEl.setAttribute("aria-hidden", "true");
@@ -59,7 +59,7 @@ class SubmitAccount {
"focus:valid:!ring-red-500",
"active:!border-red-500",
"active:valid:!border-red-500",
- "valid:!border-red-500"
+ "valid:!border-red-500",
);
this.pwAlertEl.classList.remove("opacity-0");
this.pwAlertEl.setAttribute("aria-hidden", "false");
@@ -77,14 +77,14 @@ class PwBtn {
const passwordContainer = e.target.closest("[data-input-group]");
const inpEl = passwordContainer.querySelector("input");
const invBtn = passwordContainer.querySelector(
- '[data-setting-password="invisible"]'
+ '[data-setting-password="invisible"]',
);
const visBtn = passwordContainer.querySelector(
- '[data-setting-password="visible"]'
+ '[data-setting-password="visible"]',
);
inpEl.setAttribute(
"type",
- inpEl.getAttribute("type") === "password" ? "text" : "password"
+ inpEl.getAttribute("type") === "password" ? "text" : "password",
);
if (inpEl.getAttribute("type") === "password") {
diff --git a/src/ui/static/js/bans.js b/src/ui/static/js/bans.js
new file mode 100644
index 000000000..534cb05f8
--- /dev/null
+++ b/src/ui/static/js/bans.js
@@ -0,0 +1,601 @@
+class Filter {
+ constructor(prefix = "bans") {
+ this.prefix = prefix;
+ this.container = document.querySelector(`[data-${this.prefix}-filter]`);
+ this.keyInp = document.querySelector("input#keyword");
+ this.termValue = "all";
+ this.reasonValue = "all";
+ this.initHandler();
+ }
+
+ initHandler() {
+ // REASON HANDLER
+ this.container.addEventListener("click", (e) => {
+ try {
+ if (
+ e.target
+ .closest("button")
+ .getAttribute(`data-${this.prefix}-setting-select-dropdown-btn`) ===
+ "reason"
+ ) {
+ setTimeout(() => {
+ const value = document
+ .querySelector(
+ `[data-${this.prefix}-setting-select-text="reason"]`
+ )
+ .textContent.trim();
+
+ this.reasonValue = value;
+ //run filter
+ this.filter();
+ }, 10);
+ }
+ } catch (err) {}
+ });
+ // TERM HANDLER
+ this.container.addEventListener("click", (e) => {
+ try {
+ if (
+ e.target
+ .closest("button")
+ .getAttribute(`data-${this.prefix}-setting-select-dropdown-btn`) ===
+ "term"
+ ) {
+ setTimeout(() => {
+ const value = document
+ .querySelector(`[data-${this.prefix}-setting-select-text="term"]`)
+ .textContent.trim();
+
+ this.termValue = value;
+ //run filter
+ this.filter();
+ }, 10);
+ }
+ } catch (err) {}
+ });
+ //KEYWORD HANDLER
+ this.keyInp.addEventListener("input", (e) => {
+ this.filter();
+ });
+ }
+
+ filter() {
+ const bans = document.querySelector(`[data-${this.prefix}-list]`).children;
+ if (bans.length === 0) return;
+ //reset
+ for (let i = 0; i < bans.length; i++) {
+ const el = bans[i];
+ el.classList.remove("hidden");
+ }
+ //filter type
+ this.setFilterKeyword(bans);
+ this.setFilterReason(bans);
+ this.setFilterTerm(bans);
+ }
+
+ setFilterKeyword(bans) {
+ const keyword = this.keyInp.value.trim().toLowerCase();
+ if (!keyword) return;
+ for (let i = 0; i < bans.length; i++) {
+ const el = bans[i];
+
+ const ip = this.getElAttribut(el, "ip");
+ const banStart = this.getElAttribut(el, "ban_sart");
+ const banEnd = this.getElAttribut(el, "ban_end");
+ const remain = this.getElAttribut(el, "remain");
+
+ if (
+ !ip.includes(keyword) &&
+ !banStart.includes(keyword) &&
+ !banEnd.includes(keyword) &&
+ !remain.includes(keyword)
+ )
+ el.classList.add("hidden");
+ }
+ }
+
+ setFilterTerm(bans) {
+ if (this.termValue === "all") return;
+ for (let i = 0; i < bans.length; i++) {
+ const el = bans[i];
+ const type = this.getElAttribut(el, "term");
+ if (type !== this.termValue) el.classList.add("hidden");
+ }
+ }
+
+ setFilterReason(bans) {
+ if (this.reasonValue === "all") return;
+ for (let i = 0; i < bans.length; i++) {
+ const el = bans[i];
+ const type = this.getElAttribut(el, "reason");
+ if (type !== this.reasonValue) el.classList.add("hidden");
+ }
+ }
+
+ getElAttribut(el, attr) {
+ return el
+ .querySelector(`[data-${this.prefix}-${attr}]`)
+ .getAttribute(`data-${this.prefix}-${attr}`)
+ .trim();
+ }
+}
+
+class Dropdown {
+ constructor(prefix = "bans") {
+ this.prefix = prefix;
+ this.container = document.querySelector("main");
+ this.lastDrop = "";
+ this.initDropdown();
+ }
+
+ initDropdown() {
+ this.container.addEventListener("click", (e) => {
+ //SELECT BTN LOGIC
+ try {
+ if (
+ e.target
+ .closest("button")
+ .hasAttribute(`data-${this.prefix}-setting-select`) &&
+ !e.target.closest("button").hasAttribute(`disabled`)
+ ) {
+ const btnName = e.target
+ .closest("button")
+ .getAttribute(`data-${this.prefix}-setting-select`);
+ if (this.lastDrop !== btnName) {
+ this.lastDrop = btnName;
+ this.closeAllDrop();
+ }
+
+ this.toggleSelectBtn(e);
+ }
+ } catch (err) {}
+ //SELECT DROPDOWN BTN LOGIC
+ try {
+ if (
+ e.target
+ .closest("button")
+ .hasAttribute(`data-${this.prefix}-setting-select-dropdown-btn`)
+ ) {
+ const btn = e.target.closest("button");
+ const btnValue = btn.getAttribute("value");
+ const btnSetting = btn.getAttribute(
+ `data-${this.prefix}-setting-select-dropdown-btn`
+ );
+ //stop if same value to avoid new fetching
+ const isSameVal = this.isSameValue(btnSetting, btnValue);
+ if (isSameVal) return this.hideDropdown(btnSetting);
+ //else, add new value to custom
+ this.setSelectNewValue(btnSetting, btnValue);
+ //close dropdown and change style
+ this.hideDropdown(btnSetting);
+
+ if (
+ !e.target.closest("button").hasAttribute(`data-${this.prefix}-file`)
+ ) {
+ this.changeDropBtnStyle(btnSetting, btn);
+ }
+ //show / hide filter
+ if (btnSetting === "instances") {
+ this.hideFilterOnLocal(btn.getAttribute("data-_type"));
+ }
+ }
+ } catch (err) {}
+ });
+ }
+
+ closeAllDrop() {
+ const drops = document.querySelectorAll(
+ `[data-${this.prefix}-setting-select-dropdown]`
+ );
+ drops.forEach((drop) => {
+ drop.classList.add("hidden");
+ drop.classList.remove("flex");
+ document
+ .querySelector(
+ `svg[data-${this.prefix}-setting-select="${drop.getAttribute(
+ `data-${this.prefix}-setting-select-dropdown`
+ )}"]`
+ )
+ .classList.remove("rotate-180");
+ });
+ }
+
+ isSameValue(btnSetting, value) {
+ const selectCustom = document.querySelector(
+ `[data-${this.prefix}-setting-select-text="${btnSetting}"]`
+ );
+ const currVal = selectCustom.textContent;
+ return currVal === value ? true : false;
+ }
+
+ setSelectNewValue(btnSetting, value) {
+ const selectCustom = document.querySelector(
+ `[data-${this.prefix}-setting-select="${btnSetting}"]`
+ );
+ selectCustom.querySelector(
+ `[data-${this.prefix}-setting-select-text]`
+ ).textContent = value;
+ }
+
+ hideDropdown(btnSetting) {
+ //hide dropdown
+ const dropdownEl = document.querySelector(
+ `[data-${this.prefix}-setting-select-dropdown="${btnSetting}"]`
+ );
+ dropdownEl.classList.add("hidden");
+ dropdownEl.classList.remove("flex");
+ //svg effect
+ const dropdownChevron = document.querySelector(
+ `svg[data-${this.prefix}-setting-select="${btnSetting}"]`
+ );
+ dropdownChevron.classList.remove("rotate-180");
+ }
+
+ changeDropBtnStyle(btnSetting, selectedBtn) {
+ const dropdownEl = document.querySelector(
+ `[data-${this.prefix}-setting-select-dropdown="${btnSetting}"]`
+ );
+ //reset dropdown btns
+ const btnEls = dropdownEl.querySelectorAll("button");
+
+ btnEls.forEach((btn) => {
+ btn.classList.remove(
+ "bg-primary",
+ "dark:bg-primary",
+ "text-gray-300",
+ "text-gray-300"
+ );
+ btn.classList.add("bg-white", "dark:bg-slate-700", "text-gray-700");
+ });
+ //highlight clicked btn
+ selectedBtn.classList.remove(
+ "bg-white",
+ "dark:bg-slate-700",
+ "text-gray-700"
+ );
+ selectedBtn.classList.add("dark:bg-primary", "bg-primary", "text-gray-300");
+ }
+
+ toggleSelectBtn(e) {
+ const attribute = e.target
+ .closest("button")
+ .getAttribute(`data-${this.prefix}-setting-select`);
+ //toggle dropdown
+ const dropdownEl = document.querySelector(
+ `[data-${this.prefix}-setting-select-dropdown="${attribute}"]`
+ );
+ const dropdownChevron = document.querySelector(
+ `svg[data-${this.prefix}-setting-select="${attribute}"]`
+ );
+ dropdownEl.classList.toggle("hidden");
+ dropdownEl.classList.toggle("flex");
+ dropdownChevron.classList.toggle("rotate-180");
+ }
+
+ //hide date filter on local
+ hideFilterOnLocal(type) {
+ if (type === "local") {
+ this.hideInp(`input#from-date`);
+ this.hideInp(`input#to-date`);
+ }
+
+ if (type !== "local") {
+ this.showInp(`input#from-date`);
+ this.showInp(`input#to-date`);
+ }
+ }
+
+ showInp(selector) {
+ document.querySelector(selector).closest("div").classList.add("flex");
+ document.querySelector(selector).closest("div").classList.remove("hidden");
+ }
+
+ hideInp(selector) {
+ document.querySelector(selector).closest("div").classList.add("hidden");
+ document.querySelector(selector).closest("div").classList.remove("flex");
+ }
+}
+
+class Unban {
+ constructor(prefix = "bans") {
+ this.prefix = prefix;
+ this.container = document.querySelector("main");
+ this.listEl = document.querySelector(`[data-${this.prefix}-list]`);
+ this.unbanForm = document.querySelector("#unban-items");
+ this.unbanBtn = document.querySelector(`button[data-unban-btn]`);
+ this.unbanInp = document.querySelector(`input[data-unban-inp]`);
+ this.init();
+ }
+
+ init() {
+ // Look if an item is select to enable unban button
+ this.container.addEventListener("click", (e) => {
+ try {
+ if (
+ e.target.closest("div").hasAttribute(`data-${this.prefix}-ban-select`)
+ ) {
+ // timeout to wait for select value to change
+ setTimeout(() => {
+ // Check if at least one item is selected
+ const selected = this.listEl.querySelectorAll(
+ `input[data-checked="true"]`
+ );
+
+ // Case true, enable unban button
+ if (selected.length > 0) {
+ this.unbanBtn.removeAttribute("disabled");
+ }
+
+ // Case false, disable unban button
+ if (selected.length === 0) {
+ this.unbanBtn.setAttribute("disabled", "");
+ }
+ }, 100);
+ }
+ } catch (err) {}
+ });
+ // unban button
+ this.unbanForm.addEventListener("submit", (e) => {
+ e.preventDefault();
+ if (this.unbanBtn.hasAttribute("disabled")) return;
+ // Get all selected items
+ const selected = this.listEl.querySelectorAll(
+ `input[data-checked="true"]`
+ );
+ const getDatas = [];
+ selected.forEach((el) => {
+ const data = el
+ .closest(`li[data-${this.prefix}-list-item]`)
+ .getAttribute(`data-${this.prefix}-list-item`);
+ getDatas.push(data);
+ });
+ this.unbanInp.value = JSON.stringify(getDatas);
+ this.unbanInp.setAttribute("value", JSON.stringify(getDatas));
+ this.unbanForm.submit();
+ });
+ }
+}
+
+class AddBanModal {
+ constructor() {
+ //modal elements
+ this.modal = document.querySelector("[data-bans-modal]");
+ this.openBtn = document.querySelector("button[data-add-ban]");
+ this.addBanInp = document.querySelector("input[data-ban-add-inp]");
+ this.addFieldBtn = document.querySelector("button[data-ban-add-new]");
+ this.listEl = document.querySelector(`[data-bans-add-ban-list]`);
+ this.submitBtn = document.querySelector(`button[data-bans-modal-submit]`);
+ this.removeAllFieldBtn = document.querySelector(
+ "button[data-add-ban-delete-all-item]"
+ );
+ this.formEl = document.querySelector("form[data-ban-add-form]");
+ this.itemCount = 0;
+ this.setDatepicker("0"); // for default field
+ this.init();
+ }
+
+ init() {
+ // delete item
+ this.modal.addEventListener("click", (e) => {
+ try {
+ if (e.target.hasAttribute("data-add-ban-delete-item")) {
+ e.target.closest("li").remove();
+ this.updateActionBtns();
+ }
+ } catch (e) {}
+
+ try {
+ if (e.target.hasAttribute("data-add-ban-delete-all-item")) {
+ this.listEl.querySelectorAll("li").forEach((item) => {
+ item.remove();
+ });
+ }
+ } catch (e) {}
+
+ try {
+ if (e.target.closest("button").hasAttribute("data-bans-modal-close")) {
+ this.closeModal();
+ }
+ } catch (e) {}
+
+ this.updateActionBtns();
+ });
+
+ //open modal
+ this.openBtn.addEventListener("click", (e) => {
+ this.openModal();
+ });
+
+ // add field
+ this.addFieldBtn.addEventListener("click", (e) => {
+ this.addItem();
+ this.updateActionBtns();
+ });
+
+ // Check that all inputs have a value to submit
+ this.listEl.addEventListener("input", (e) => {
+ this.checkInpValidity();
+ });
+
+ this.listEl.addEventListener("change", (e) => {
+ this.checkInpValidity();
+ });
+
+ this.formEl.addEventListener("submit", (e) => {
+ e.preventDefault();
+ // prepare data
+ const data = [];
+ this.listEl.querySelectorAll("li").forEach((item) => {
+ const ip = item.querySelector("input[data-bans-add-ip]").value;
+ const banEnd = item
+ .querySelector("input[data-bans-add-ban-end]")
+ .getAttribute("data-timestamp");
+ data.push({
+ ip: ip,
+ ban_end: +banEnd,
+ ban_start: +Date.now().toString().substring(0, 10),
+ reason: "ui",
+ });
+ });
+ this.addBanInp.setAttribute("value", JSON.stringify(data));
+ this.addBanInp.value = JSON.stringify(data);
+ this.formEl.submit();
+ });
+ }
+
+ openModal() {
+ this.modal.classList.remove("hidden");
+ this.modal.classList.add("flex");
+ }
+
+ closeModal() {
+ this.modal.classList.add("hidden");
+ this.modal.classList.remove("flex");
+ }
+
+ checkInpValidity() {
+ const inps = this.listEl.querySelectorAll("input");
+ let isAllValid = true;
+ for (let i = 0; i < inps.length; i++) {
+ const inpEl = inps[i];
+ if (!inpEl.checkValidity() || !inpEl.value) {
+ isAllValid = false;
+ break;
+ }
+ }
+
+ isAllValid
+ ? this.submitBtn.removeAttribute("disabled")
+ : this.submitBtn.setAttribute("disabled", "");
+ }
+
+ // Check if items and update button disabled/enabled states
+ updateActionBtns() {
+ const items = this.listEl.querySelectorAll("li");
+ const itemsCount = items.length;
+
+ itemsCount
+ ? this.removeAllFieldBtn.removeAttribute("disabled")
+ : this.removeAllFieldBtn.setAttribute("disabled", "");
+
+ itemsCount ? null : this.submitBtn.setAttribute("disabled", "");
+ }
+
+ addItem() {
+ // add item
+ this.itemCount++;
+ let item = `
+
+ ip
+
+
+
+
+ `;
+ let cleanHTML = DOMPurify.sanitize(item);
+ this.listEl.insertAdjacentHTML("beforeend", cleanHTML);
+ this.setDatepicker(this.itemCount);
+ }
+
+ setDatepicker(id) {
+ const defaultDate = +(Date.now() + 3600000 * 24);
+ const inpEl = document.querySelector(`input#ban-end-${id}`);
+ inpEl.setAttribute("data-timestamp", defaultDate.toString().substring(0, 10));
+
+ // instantiate datepicker
+ const dateOptions = {
+ locale: "en",
+ dateFormat: "m/d/Y H:i:S",
+ defaultDate: defaultDate,
+ enableTime: true,
+ enableSeconds: true,
+ time_24hr: true,
+ minuteIncrement: 1,
+ onChange(selectedDates, dateStr, instance) {
+ // Get date to timestamp
+ const pickStamp = +Date.parse(new Date(dateStr).toString());
+ const nowStamp = +Date.now();
+
+ // Case pick is before current date
+ if (pickStamp < nowStamp) {
+ inpEl.setAttribute("data-timestamp", defaultDate.toString().substring(0, 10));
+ return instance.setDate(defaultDate);
+ }
+
+ // Case right value
+ // Set timestamp in seconds in the related input
+ const convertToS = +pickStamp.toString().substring(0, 10);
+
+ inpEl.setAttribute("data-timestamp", convertToS);
+ },
+ };
+
+ flatpickr(`input#ban-end-${id}`, dateOptions);
+ }
+}
+
+const setDropdown = new Dropdown();
+const setFilter = new Filter();
+const setUnban = new Unban();
+const setModal = new AddBanModal();
diff --git a/src/ui/static/js/jobs.js b/src/ui/static/js/jobs.js
index 019509fcb..4c73e5f2e 100644
--- a/src/ui/static/js/jobs.js
+++ b/src/ui/static/js/jobs.js
@@ -47,7 +47,9 @@ class Dropdown {
//close dropdown and change style
this.hideDropdown(btnSetting);
- if (!e.target.closest("button").hasAttribute(`data-${prefix}-file`)) {
+ if (
+ !e.target.closest("button").hasAttribute(`data-${this.prefix}-file`)
+ ) {
this.changeDropBtnStyle(btnSetting, btn);
}
//show / hide filter
diff --git a/src/ui/static/js/plugins.js b/src/ui/static/js/plugins.js
index 71b5bea71..1e17858ba 100644
--- a/src/ui/static/js/plugins.js
+++ b/src/ui/static/js/plugins.js
@@ -111,13 +111,7 @@ class Dropdown {
const btnEls = dropdownEl.querySelectorAll("button");
btnEls.forEach((btn) => {
- btn.classList.remove(
- "dark:bg-primary",
- "bg-primary",
- "bg-primary",
- "text-gray-300",
- "text-gray-300",
- );
+ btn.classList.remove("dark:bg-primary", "bg-primary", "text-gray-300");
btn.classList.add("bg-white", "dark:bg-slate-700", "text-gray-700");
});
//highlight clicked btn
diff --git a/src/ui/static/js/reports.js b/src/ui/static/js/reports.js
new file mode 100644
index 000000000..aab6932b9
--- /dev/null
+++ b/src/ui/static/js/reports.js
@@ -0,0 +1,372 @@
+class Filter {
+ constructor(prefix = "reports") {
+ this.prefix = prefix;
+ this.container = document.querySelector(`[data-${this.prefix}-filter]`);
+ this.keyInp = document.querySelector("input#keyword");
+ this.methodValue = "all";
+ this.statusValue = "all";
+ this.reasonValue = "all";
+ this.countryValue = "all";
+ this.initHandler();
+ }
+
+ initHandler() {
+ //METHOD HANDLER
+ this.container.addEventListener("click", (e) => {
+ try {
+ if (
+ e.target
+ .closest("button")
+ .getAttribute(`data-${this.prefix}-setting-select-dropdown-btn`) ===
+ "method"
+ ) {
+ setTimeout(() => {
+ const value = document
+ .querySelector(
+ `[data-${this.prefix}-setting-select-text="method"]`,
+ )
+ .textContent.trim();
+
+ this.methodValue = value;
+ //run filter
+ this.filter();
+ }, 10);
+ }
+ } catch (err) {}
+ });
+ //COUNTRY HANDLER
+ this.container.addEventListener("click", (e) => {
+ try {
+ if (
+ e.target
+ .closest("button")
+ .getAttribute(`data-${this.prefix}-setting-select-dropdown-btn`) ===
+ "country"
+ ) {
+ setTimeout(() => {
+ const value = document
+ .querySelector(
+ `[data-${this.prefix}-setting-select-text="country"]`,
+ )
+ .textContent.trim();
+
+ this.countryValue = value;
+ //run filter
+ this.filter();
+ }, 10);
+ }
+ } catch (err) {}
+ });
+ //STATUS HANDLER
+ this.container.addEventListener("click", (e) => {
+ try {
+ if (
+ e.target
+ .closest("button")
+ .getAttribute(`data-${this.prefix}-setting-select-dropdown-btn`) ===
+ "status"
+ ) {
+ setTimeout(() => {
+ const value = document
+ .querySelector(
+ `[data-${this.prefix}-setting-select-text="status"]`,
+ )
+ .textContent.trim();
+
+ this.statusValue = value;
+ //run filter
+ this.filter();
+ }, 10);
+ }
+ } catch (err) {}
+ });
+ // REASON HANDLER
+ +this.container.addEventListener("click", (e) => {
+ try {
+ if (
+ e.target
+ .closest("button")
+ .getAttribute(`data-${this.prefix}-setting-select-dropdown-btn`) ===
+ "reason"
+ ) {
+ setTimeout(() => {
+ const value = document
+ .querySelector(
+ `[data-${this.prefix}-setting-select-text="reason"]`,
+ )
+ .textContent.trim();
+
+ this.reasonValue = value;
+ //run filter
+ this.filter();
+ }, 10);
+ }
+ } catch (err) {}
+ });
+ //KEYWORD HANDLER
+ this.keyInp.addEventListener("input", (e) => {
+ this.filter();
+ });
+ }
+
+ filter() {
+ const requests = document.querySelector(
+ `[data-${this.prefix}-list]`,
+ ).children;
+ if (requests.length === 0) return;
+ //reset
+ for (let i = 0; i < requests.length; i++) {
+ const el = requests[i];
+ el.classList.remove("hidden");
+ }
+ //filter type
+ this.setFilterMethod(requests);
+ this.setFilterKeyword(requests);
+ this.setFilterStatus(requests);
+ this.setFilterReason(requests);
+ this.setFilterCountry(requests);
+ }
+
+ setFilterMethod(requests) {
+ if (this.methodValue === "all") return;
+ for (let i = 0; i < requests.length; i++) {
+ const el = requests[i];
+ const type = this.getElAttribut(el, "method");
+ if (type !== this.methodValue) el.classList.add("hidden");
+ }
+ }
+
+ setFilterMethod(requests) {
+ if (this.countryValue === "all") return;
+ for (let i = 0; i < requests.length; i++) {
+ const el = requests[i];
+ const type = this.getElAttribut(el, "country");
+ if (type !== this.countryValue) el.classList.add("hidden");
+ }
+ }
+
+ setFilterKeyword(requests) {
+ const keyword = this.keyInp.value.trim().toLowerCase();
+ if (!keyword) return;
+ for (let i = 0; i < requests.length; i++) {
+ const el = requests[i];
+
+ const url = this.getElAttribut(el, "url");
+ const date = this.getElAttribut(el, "date");
+ const ip = this.getElAttribut(el, "ip");
+ const data = this.getElAttribut(el, "data");
+
+ if (
+ !url.includes(keyword) &&
+ !date.includes(keyword) &&
+ !ip.includes(keyword) &&
+ !data.includes(keyword)
+ )
+ el.classList.add("hidden");
+ }
+ }
+
+ setFilterStatus(requests) {
+ if (this.statusValue === "all") return;
+ for (let i = 0; i < requests.length; i++) {
+ const el = requests[i];
+ const type = this.getElAttribut(el, "status");
+ if (type !== this.statusValue) el.classList.add("hidden");
+ }
+ }
+
+ setFilterReason(requests) {
+ if (this.reasonValue === "all") return;
+ for (let i = 0; i < requests.length; i++) {
+ const el = requests[i];
+ const type = this.getElAttribut(el, "reason");
+ if (type !== this.reasonValue) el.classList.add("hidden");
+ }
+ }
+
+ getElAttribut(el, attr) {
+ return el
+ .querySelector(`[data-${this.prefix}-${attr}]`)
+ .getAttribute(`data-${this.prefix}-${attr}`)
+ .trim();
+ }
+}
+
+class Dropdown {
+ constructor(prefix = "reports") {
+ this.prefix = prefix;
+ this.container = document.querySelector("main");
+ this.lastDrop = "";
+ this.initDropdown();
+ }
+
+ initDropdown() {
+ this.container.addEventListener("click", (e) => {
+ //SELECT BTN LOGIC
+ try {
+ if (
+ e.target
+ .closest("button")
+ .hasAttribute(`data-${this.prefix}-setting-select`) &&
+ !e.target.closest("button").hasAttribute(`disabled`)
+ ) {
+ const btnName = e.target
+ .closest("button")
+ .getAttribute(`data-${this.prefix}-setting-select`);
+ if (this.lastDrop !== btnName) {
+ this.lastDrop = btnName;
+ this.closeAllDrop();
+ }
+
+ this.toggleSelectBtn(e);
+ }
+ } catch (err) {}
+ //SELECT DROPDOWN BTN LOGIC
+ try {
+ if (
+ e.target
+ .closest("button")
+ .hasAttribute(`data-${this.prefix}-setting-select-dropdown-btn`)
+ ) {
+ const btn = e.target.closest("button");
+ const btnValue = btn.getAttribute("value");
+ const btnSetting = btn.getAttribute(
+ `data-${this.prefix}-setting-select-dropdown-btn`,
+ );
+ //stop if same value to avoid new fetching
+ const isSameVal = this.isSameValue(btnSetting, btnValue);
+ if (isSameVal) return this.hideDropdown(btnSetting);
+ //else, add new value to custom
+ this.setSelectNewValue(btnSetting, btnValue);
+ //close dropdown and change style
+ this.hideDropdown(btnSetting);
+
+ if (
+ !e.target.closest("button").hasAttribute(`data-${this.prefix}-file`)
+ ) {
+ this.changeDropBtnStyle(btnSetting, btn);
+ }
+ //show / hide filter
+ if (btnSetting === "instances") {
+ this.hideFilterOnLocal(btn.getAttribute("data-_type"));
+ }
+ }
+ } catch (err) {}
+ });
+ }
+
+ closeAllDrop() {
+ const drops = document.querySelectorAll(
+ `[data-${this.prefix}-setting-select-dropdown]`,
+ );
+ drops.forEach((drop) => {
+ drop.classList.add("hidden");
+ drop.classList.remove("flex");
+ document
+ .querySelector(
+ `svg[data-${this.prefix}-setting-select="${drop.getAttribute(
+ `data-${this.prefix}-setting-select-dropdown`,
+ )}"]`,
+ )
+ .classList.remove("rotate-180");
+ });
+ }
+
+ isSameValue(btnSetting, value) {
+ const selectCustom = document.querySelector(
+ `[data-${this.prefix}-setting-select-text="${btnSetting}"]`,
+ );
+ const currVal = selectCustom.textContent;
+ return currVal === value ? true : false;
+ }
+
+ setSelectNewValue(btnSetting, value) {
+ const selectCustom = document.querySelector(
+ `[data-${this.prefix}-setting-select="${btnSetting}"]`,
+ );
+ selectCustom.querySelector(
+ `[data-${this.prefix}-setting-select-text]`,
+ ).textContent = value;
+ }
+
+ hideDropdown(btnSetting) {
+ //hide dropdown
+ const dropdownEl = document.querySelector(
+ `[data-${this.prefix}-setting-select-dropdown="${btnSetting}"]`,
+ );
+ dropdownEl.classList.add("hidden");
+ dropdownEl.classList.remove("flex");
+ //svg effect
+ const dropdownChevron = document.querySelector(
+ `svg[data-${this.prefix}-setting-select="${btnSetting}"]`,
+ );
+ dropdownChevron.classList.remove("rotate-180");
+ }
+
+ changeDropBtnStyle(btnSetting, selectedBtn) {
+ const dropdownEl = document.querySelector(
+ `[data-${this.prefix}-setting-select-dropdown="${btnSetting}"]`,
+ );
+ //reset dropdown btns
+ const btnEls = dropdownEl.querySelectorAll("button");
+
+ btnEls.forEach((btn) => {
+ btn.classList.remove(
+ "bg-primary",
+ "dark:bg-primary",
+ "text-gray-300",
+ "text-gray-300",
+ );
+ btn.classList.add("bg-white", "dark:bg-slate-700", "text-gray-700");
+ });
+ //highlight clicked btn
+ selectedBtn.classList.remove(
+ "bg-white",
+ "dark:bg-slate-700",
+ "text-gray-700",
+ );
+ selectedBtn.classList.add("dark:bg-primary", "bg-primary", "text-gray-300");
+ }
+
+ toggleSelectBtn(e) {
+ const attribute = e.target
+ .closest("button")
+ .getAttribute(`data-${this.prefix}-setting-select`);
+ //toggle dropdown
+ const dropdownEl = document.querySelector(
+ `[data-${this.prefix}-setting-select-dropdown="${attribute}"]`,
+ );
+ const dropdownChevron = document.querySelector(
+ `svg[data-${this.prefix}-setting-select="${attribute}"]`,
+ );
+ dropdownEl.classList.toggle("hidden");
+ dropdownEl.classList.toggle("flex");
+ dropdownChevron.classList.toggle("rotate-180");
+ }
+
+ //hide date filter on local
+ hideFilterOnLocal(type) {
+ if (type === "local") {
+ this.hideInp(`input#from-date`);
+ this.hideInp(`input#to-date`);
+ }
+
+ if (type !== "local") {
+ this.showInp(`input#from-date`);
+ this.showInp(`input#to-date`);
+ }
+ }
+
+ showInp(selector) {
+ document.querySelector(selector).closest("div").classList.add("flex");
+ document.querySelector(selector).closest("div").classList.remove("hidden");
+ }
+
+ hideInp(selector) {
+ document.querySelector(selector).closest("div").classList.add("hidden");
+ document.querySelector(selector).closest("div").classList.remove("flex");
+ }
+}
+
+const setDropdown = new Dropdown();
+const setFilter = new Filter();
diff --git a/src/ui/static/js/services.js b/src/ui/static/js/services.js
index 3e938f1ab..89fe7e974 100644
--- a/src/ui/static/js/services.js
+++ b/src/ui/static/js/services.js
@@ -83,6 +83,37 @@ class ServiceModal {
this.openModal();
}
} catch (err) {}
+ // clone action
+ try {
+ if (
+ e.target.closest("button").getAttribute("data-services-action") ===
+ "clone"
+ ) {
+ //set form info and right form
+ const [action, serviceName] = this.getActionAndServName(e.target);
+ this.setForm(action, serviceName, serviceName, this.formNewEdit);
+ //set default value with method default
+ //get service data and parse it
+ //multiple type logic is launch at same time on relate class
+ const servicesSettings = e.target
+ .closest("[data-services-service]")
+ .querySelector("[data-services-settings]")
+ .getAttribute("data-value");
+ const obj = JSON.parse(servicesSettings);
+ this.updateModalData(obj, true);
+ // server name is unset
+ const inpServName = document.querySelector("input#SERVER_NAME");
+ inpServName.getAttribute("value", "");
+ inpServName.removeAttribute("disabled", "");
+ inpServName.value = "";
+ // clone is UI creation, so no setting should be disabled
+
+ //show modal
+ this.resetFilterInp();
+ this.changeSubmitBtn("CREATE", "valid-btn");
+ this.openModal(); //server name is unset
+ }
+ } catch (err) {}
//new action
try {
if (
@@ -219,10 +250,11 @@ class ServiceModal {
setForm(action, serviceName, oldServName, formEl) {
this.modalTitle.textContent = `${action} ${serviceName}`;
- formEl.setAttribute("id", `form-${action}-${serviceName}`);
+ const operation = action === "clone" ? "new" : action;
+ formEl.setAttribute("id", `form-${operation}-${serviceName}`);
const opeInp = formEl.querySelector(`input[name="operation"]`);
- opeInp.setAttribute("value", action);
- opeInp.value = action;
+ opeInp.setAttribute("value", operation);
+ opeInp.value = operation;
if (action === "edit" || action === "new") {
this.showNewEditForm();
@@ -231,6 +263,13 @@ class ServiceModal {
oldNameInp.value = oldServName;
}
+ if (action === "clone") {
+ this.showNewEditForm();
+ const oldNameInp = formEl.querySelector(`input[name="OLD_SERVER_NAME"]`);
+ oldNameInp.setAttribute("value", "");
+ oldNameInp.value = "";
+ }
+
if (action === "delete") {
this.showDeleteForm();
formEl.querySelector(`[data-services-modal-text]`).textContent =
@@ -286,7 +325,7 @@ class ServiceModal {
this.modalTabsHeader.classList.remove("hidden");
}
- updateModalData(settings) {
+ updateModalData(settings, forceEnabled = false) {
//use this to select inputEl and change value
for (const [key, data] of Object.entries(settings)) {
//change format to match id
@@ -350,14 +389,14 @@ class ServiceModal {
inp.setAttribute("data-method", method);
}
- //check disabled/enabled after setting values and methods
- this.setDisabledServ(inp, method, global);
+ if (!forceEnabled) this.setDisabledState(inp, method, global);
+ if (forceEnabled) inp.removeAttribute("disabled");
});
} catch (err) {}
}
}
- setDisabledServ(inp, method, global) {
+ setDisabledState(inp, method, global) {
if (global) return inp.removeAttribute("disabled");
if (method === "ui" || method === "default") {
diff --git a/src/ui/static/js/totp.js b/src/ui/static/js/totp.js
index 8dd1fd9d5..17b600c87 100644
--- a/src/ui/static/js/totp.js
+++ b/src/ui/static/js/totp.js
@@ -12,8 +12,8 @@ class BackLogin {
"href",
window.location.href.replace(
`/${this.currEndpoint}`,
- `/${this.backEndpoint}`
- )
+ `/${this.backEndpoint}`,
+ ),
);
});
});
diff --git a/src/ui/styles.css b/src/ui/styles.css
index e67dc6c81..9bacc7433 100644
--- a/src/ui/styles.css
+++ b/src/ui/styles.css
@@ -25,23 +25,23 @@
}
.close-btn {
- @apply dark:brightness-90 inline-block px-6 py-3 font-bold text-center text-red-500 border border-red-500 uppercase align-middle transition-all rounded-lg cursor-pointer dark:bg-gray-200 dark:hover:brightness-75 bg-white hover:bg-white/80 focus:bg-white/80 leading-normal ease-in tracking-tight-rem shadow-xs hover:-translate-y-px active:opacity-85 hover:shadow-md;
+ @apply dark:brightness-90 inline-block px-6 py-3 font-bold text-center text-red-500 border border-red-500 uppercase align-middle transition-all rounded-lg cursor-pointer dark:bg-gray-200 dark:hover:brightness-75 bg-white hover:bg-white/80 focus:bg-white/80 leading-normal ease-in tracking-tight-rem shadow-xs hover:-translate-y-px active:opacity-85 hover:shadow-md disabled:cursor-not-allowed dark:disabled:text-gray-300 disabled:text-gray-700 disabled:bg-gray-400 disabled:border-gray-400/0 dark:disabled:bg-gray-700 dark:disabled:border-gray-700/0 disabled:hover:translate-y-0 disabled:hover:bg-gray-400 disabled:hover:border-gray-400/0 dark:disabled:hover:translate-y-0 dark:disabled:hover:bg-gray-700 dark:disabled:hover:border-gray-700/0;
}
.valid-btn {
- @apply tracking-wide dark:brightness-90 inline-block px-6 py-3 font-bold text-center text-white uppercase align-middle transition-all rounded-lg cursor-pointer bg-green-500 hover:bg-green-500/80 focus:bg-green-500/80 leading-normal ease-in shadow-xs hover:-translate-y-px active:opacity-85 hover:shadow-md;
+ @apply tracking-wide dark:brightness-90 inline-block px-6 py-3 font-bold text-center text-white uppercase align-middle transition-all rounded-lg cursor-pointer bg-green-500 hover:bg-green-500/80 focus:bg-green-500/80 leading-normal ease-in shadow-xs hover:-translate-y-px active:opacity-85 hover:shadow-md disabled:cursor-not-allowed dark:disabled:text-gray-300 disabled:text-gray-700 disabled:bg-gray-400 disabled:border-gray-400/0 dark:disabled:bg-gray-700 dark:disabled:border-gray-700/0 disabled:hover:translate-y-0 disabled:hover:bg-gray-400 disabled:hover:border-gray-400/0 dark:disabled:hover:translate-y-0 dark:disabled:hover:bg-gray-700 dark:disabled:hover:border-gray-700/0;
}
.delete-btn {
- @apply tracking-wide dark:brightness-90 inline-block px-6 py-3 font-bold text-center text-white uppercase align-middle transition-all rounded-lg cursor-pointer bg-red-500 hover:bg-red-500/80 focus:bg-red-500/80 leading-normal ease-in shadow-xs hover:-translate-y-px active:opacity-85 hover:shadow-md;
+ @apply tracking-wide dark:brightness-90 inline-block px-6 py-3 font-bold text-center text-white uppercase align-middle transition-all rounded-lg cursor-pointer bg-red-500 hover:bg-red-500/80 focus:bg-red-500/80 leading-normal ease-in shadow-xs hover:-translate-y-px active:opacity-85 hover:shadow-md disabled:cursor-not-allowed dark:disabled:text-gray-300 disabled:text-gray-700 disabled:bg-gray-400 disabled:border-gray-400/0 dark:disabled:bg-gray-700 dark:disabled:border-gray-700/0 disabled:hover:translate-y-0 disabled:hover:bg-gray-400 disabled:hover:border-gray-400/0 dark:disabled:hover:translate-y-0 dark:disabled:hover:bg-gray-700 dark:disabled:hover:border-gray-700/0;
}
.edit-btn {
- @apply tracking-wide dark:brightness-90 inline-block px-6 py-3 font-bold text-center text-white uppercase align-middle transition-all rounded-lg cursor-pointer bg-yellow-500 hover:bg-yellow-500/80 focus:bg-yellow-500/80 leading-normal ease-in shadow-xs hover:-translate-y-px active:opacity-85 hover:shadow-md;
+ @apply tracking-wide dark:brightness-90 inline-block px-6 py-3 font-bold text-center text-white uppercase align-middle transition-all rounded-lg cursor-pointer bg-yellow-500 hover:bg-yellow-500/80 focus:bg-yellow-500/80 leading-normal ease-in shadow-xs hover:-translate-y-px active:opacity-85 hover:shadow-md disabled:cursor-not-allowed dark:disabled:text-gray-300 disabled:text-gray-700 disabled:bg-gray-400 disabled:border-gray-400/0 dark:disabled:bg-gray-700 dark:disabled:border-gray-700/0 disabled:hover:translate-y-0 disabled:hover:bg-gray-400 disabled:hover:border-gray-400/0 dark:disabled:hover:translate-y-0 dark:disabled:hover:bg-gray-700 dark:disabled:hover:border-gray-700/0;
}
.info-btn {
- @apply tracking-wide dark:brightness-90 inline-block px-6 py-3 font-bold text-center text-white uppercase align-middle transition-all rounded-lg cursor-pointer bg-sky-500 hover:bg-sky-500/80 focus:bg-sky-500/80 leading-normal ease-in shadow-xs hover:-translate-y-px active:opacity-85 hover:shadow-md;
+ @apply tracking-wide dark:brightness-90 inline-block px-6 py-3 font-bold text-center text-white uppercase align-middle transition-all rounded-lg cursor-pointer bg-sky-500 hover:bg-sky-500/80 focus:bg-sky-500/80 leading-normal ease-in shadow-xs hover:-translate-y-px active:opacity-85 hover:shadow-md disabled:cursor-not-allowed dark:disabled:text-gray-300 disabled:text-gray-700 disabled:bg-gray-400 disabled:border-gray-400/0 dark:disabled:bg-gray-700 dark:disabled:border-gray-700/0 disabled:hover:translate-y-0 disabled:hover:bg-gray-400 disabled:hover:border-gray-400/0 dark:disabled:hover:translate-y-0 dark:disabled:hover:bg-gray-700 dark:disabled:hover:border-gray-700/0;
}
/*----------------------------------------------*/
diff --git a/src/ui/templates/bans.html b/src/ui/templates/bans.html
new file mode 100644
index 000000000..6824c1e90
--- /dev/null
+++ b/src/ui/templates/bans.html
@@ -0,0 +1,374 @@
+{% extends "base.html" %} {% block content %} {% set current_endpoint =
+url_for(request.endpoint)[1:].split("/")[-1].strip() %}
+
+{% set reasons = [] %}
+{% set terms = [] %}
+
+{% for ban in bans %}
+ {% if ban["reason"] not in reasons %}
+ {% set reasons = reasons.append(ban["reason"]) %}
+ {% endif %}
+ {% if ban["term"] not in terms %}
+ {% set terms = terms.append(ban["term"]) %}
+ {% endif %}
+{% endfor %}
+
+
+
+
+ Add ban
+
+
+
+
+
+
+
+
+
+
+
+
+
+
INFO
+
+
+ BANS TOTAL
+
+
+ {{bans|length}}
+
+
+
+
+ TOP REASON
+
+
+ {{top_reason}}
+
+
+
+
+
+
+
+
FILTER
+
+
+
+
+ Search
+
+ search
+
+
+
+
+
+
+
+ Reason
+
+
+ all
+
+
+
+
+
+
+
+
+
+ all
+
+ {% for reason in reasons %}
+
+ {{reason}}
+
+ {% endfor %}
+
+
+
+
+
+
+
+
+ Range
+
+
+ all
+
+
+
+
+
+
+
+
+
+ all
+
+ {% for term in terms %}
+
+ {{term}}
+
+ {% endfor %}
+
+
+
+
+
+
+
+
+
+
+
+
+
BANS LIST
+
+
+
+
+
+
+
+
+ Select
+
+
+ IP
+
+
+ Reason
+
+
+ Ban start
+
+
+ Ban end
+
+
+ Remain
+
+
+ Term
+
+
+
+
+ {% for ban in bans %}
+
+
+
+
Ban ip {{ loop.index}}
+
+
+
+
+
+
+
+ {{ban['ip']}}
+
+
+ {{ban["reason"]}}
+
+
+ {{ban["ban_start"]}}
+
+
+ {{ban["ban_end"]}}
+
+
+ {{ban["remain"]}}
+
+
+ {{ban["term"]}}
+
+
+ {% endfor %}
+
+
+
+
+
+
+
+
+
+
+{% include "bans_modal.html" %}
+
+{% endblock %}
diff --git a/src/ui/templates/bans_modal.html b/src/ui/templates/bans_modal.html
new file mode 100644
index 000000000..ee9a9c02c
--- /dev/null
+++ b/src/ui/templates/bans_modal.html
@@ -0,0 +1,211 @@
+
+
+
+
+
+
+ ADD BANS
+
+
+
+
+
+
+
+
+
+ Entry
+
+
+
+
+
+
+ Delete all
+
+
+
+
+
+
+
+
+
+
+
+
+ IP
+
+
+ Ban end
+
+
+ Delete
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/src/ui/templates/head.html b/src/ui/templates/head.html
index da23effb1..4dd27eb73 100644
--- a/src/ui/templates/head.html
+++ b/src/ui/templates/head.html
@@ -45,5 +45,12 @@
{% elif current_endpoint == "account" %}
+ {% elif current_endpoint == "reports" %}
+
+ {% elif current_endpoint == "bans" %}
+
+
+
+
{% endif %}
diff --git a/src/ui/templates/jobs.html b/src/ui/templates/jobs.html
index 64030f728..f752cac29 100644
--- a/src/ui/templates/jobs.html
+++ b/src/ui/templates/jobs.html
@@ -2,7 +2,7 @@
url_for(request.endpoint)[1:].split("/")[-1].strip() %}
INFO
@@ -35,7 +35,7 @@ url_for(request.endpoint)[1:].split("/")[-1].strip() %}
FILTER
@@ -197,215 +197,220 @@ url_for(request.endpoint)[1:].split("/")[-1].strip() %}
-
-
JOBS
-
-
-
-
- Name
-
-
- Last run
-
-
- Every
-
-
- Reload
-
-
- Success
-
-
- Files
-
-
-
-
- {% for job_name, value in jobs.items() %}
-
-
+ JOBS LIST
+
+
+
+
+
+
-
+
+ Last run
+
+
+ Every
+
+
+ Reload
+
+
+ Success
+
+
+ Files
+
+
+
+
-
{% endblock %}
diff --git a/src/ui/templates/loading.html b/src/ui/templates/loading.html
index 1bc3834c4..60db9fe5a 100644
--- a/src/ui/templates/loading.html
+++ b/src/ui/templates/loading.html
@@ -5,9 +5,8 @@
{{ message }}...
diff --git a/src/ui/templates/logs.html b/src/ui/templates/logs.html
index 4fb5412fe..d2aa51288 100644
--- a/src/ui/templates/logs.html
+++ b/src/ui/templates/logs.html
@@ -67,6 +67,7 @@ url_for(request.endpoint)[1:].split("/")[-1].strip().replace('_', '-') %}
>
From date
+
@@ -85,6 +90,7 @@ url_for(request.endpoint)[1:].split("/")[-1].strip().replace('_', '-') %}
>
To date (default today)
+
@@ -104,6 +114,7 @@ url_for(request.endpoint)[1:].split("/")[-1].strip().replace('_', '-') %}
>
Update delay (in seconds)
+
FILTERS
@@ -279,31 +290,42 @@ url_for(request.endpoint)[1:].split("/")[-1].strip().replace('_', '-') %}
-
-
LOGS
-
-
-
-
- Type
-
-
- Description
-
-
-
-
-
+
+
LOGS
+
+
+
+
+
+
+
+
+
+ Type
+
+
+ Description
+
+
+
+
+
+
+
+
+
-
{% endblock %}
diff --git a/src/ui/templates/menu.html b/src/ui/templates/menu.html
index e5c4a4bf0..a4973626b 100644
--- a/src/ui/templates/menu.html
+++ b/src/ui/templates/menu.html
@@ -133,20 +133,12 @@
Instances
Logs
+ Reporting
+
+
+
+
+
+
+ Bans
+
+
+
+
+
+
+
+
+
+ Logs
+
+
+
+
diff --git a/src/ui/templates/plugins.html b/src/ui/templates/plugins.html
index fc8de90a3..ea0197556 100644
--- a/src/ui/templates/plugins.html
+++ b/src/ui/templates/plugins.html
@@ -4,7 +4,7 @@ include "plugins_modal.html" %}
INFO
@@ -113,7 +113,7 @@ include "plugins_modal.html" %}
FILTER
diff --git a/src/ui/templates/plugins_modal.html b/src/ui/templates/plugins_modal.html
index db19d7dc0..d0679294d 100644
--- a/src/ui/templates/plugins_modal.html
+++ b/src/ui/templates/plugins_modal.html
@@ -5,7 +5,7 @@
>
-
Close
Delete
diff --git a/src/ui/templates/reports.html b/src/ui/templates/reports.html
new file mode 100644
index 000000000..f5dfa2ed3
--- /dev/null
+++ b/src/ui/templates/reports.html
@@ -0,0 +1,493 @@
+{% extends "base.html" %} {% block content %} {% set current_endpoint =
+url_for(request.endpoint)[1:].split("/")[-1].strip() %}
+
+{% set methods = [] %}
+{% set codes = [] %}
+{% set reasons = [] %}
+{% set countries = [] %}
+
+
+{% for report in reports %}
+ {% if report["method"] not in methods %}
+ {% set methods = methods.append(report["method"]) %}
+ {% endif %}
+ {% if report["status"] not in codes %}
+ {% set codes = codes.append(report["status"]) %}
+ {% endif %}
+ {% if report["reason"] not in reasons %}
+ {% set reasons = reasons.append(report["reason"]) %}
+ {% endif %}
+ {% if report["country"] not in countries %}
+ {% set countries = countries.append(report["country"]) %}
+ {% endif %}
+{% endfor %}
+
+
+
+
+
+
No reports found
+
+
+
+{% if reports|length != 0 %}
+
+
INFO
+
+
+ REPORTING TOTAL
+
+
+ {{ total_reports }}
+
+
+
+
+ TOP REASON
+
+
+ {{top_reason}}
+
+
+
+
+ TOP STATUS CODE
+
+
+ {{top_code}}
+
+
+
+
+
+
+
+
FILTER
+
+
+
+
+ Search
+
+ search
+
+
+
+
+
+
+
+ Country
+
+
+ all
+
+
+
+
+
+
+
+
+
+ all
+
+ {% for country in countries %}
+
+ {{country}}
+
+ {% endfor %}
+
+
+
+
+
+
+
+
+ Method
+
+
+ all
+
+
+
+
+
+
+
+
+
+ all
+
+ {% for method in methods %}
+
+ {{method}}
+
+ {% endfor %}
+
+
+
+
+
+
+
+
+
+ Status code
+
+
+ all
+
+
+
+
+
+
+
+
+
+ all
+
+ {% for code in codes %}
+
+ {{code}}
+
+ {% endfor %}
+
+
+
+
+
+
+
+
+ Reason
+
+
+ all
+
+
+
+
+
+
+
+
+
+ all
+
+ {% for reason in reasons %}
+
+ {{reason}}
+
+ {% endfor %}
+
+
+
+
+
+
+
+
+
+
+
REPORTING
+
+
+
+
+
+
+ Date
+
+
+ IP
+
+
+ Country
+
+
+ Method
+
+
+ URL
+
+
+ Code
+
+
+ User agent
+
+
+ Reason
+
+
+ Data
+
+
+
+
+
+
+
+
+{%endif%}
+
+{% endblock %}
diff --git a/src/ui/templates/services.html b/src/ui/templates/services.html
index c91f0407a..3b85dbba9 100644
--- a/src/ui/templates/services.html
+++ b/src/ui/templates/services.html
@@ -7,15 +7,19 @@
data-services-action="new"
data-services-name="service"
type="button"
- class="dark:bg-green-500/90 duration-300 dark:opacity-90 w-80 inline-block px-6 py-3 font-bold text-center text-white uppercase align-middle transition-all rounded-lg cursor-pointer bg-green-500 hover:bg-green-500/80 focus:bg-green-500/80 leading-normal text-base ease-in tracking-tight-rem shadow-xs bg-150 bg-x-25 hover:-translate-y-px active:opacity-85 hover:shadow-md"
+ class="dark:bg-green-500/90 duration-300 dark:opacity-90 w-80 flex justify-center items-center px-6 py-3 font-bold text-center text-white uppercase align-middle transition-all rounded-lg cursor-pointer bg-green-500 hover:bg-green-500/80 focus:bg-green-500/80 leading-normal text-base ease-in tracking-tight-rem shadow-xs bg-150 bg-x-25 hover:-translate-y-px active:opacity-85 hover:shadow-md"
>
- New SERVICE
+
new service
+
+
+
+
{% if services|length == 0 %}
@@ -29,7 +33,7 @@
services_batched %} {% set id_server_name =
service["SERVER_NAME"]['value'].replace(".", "-") %}
@@ -355,6 +359,19 @@
+
+
+
+
+
+
+
= 12:
+ years += 1
+ months -= 12
+ days, seconds = divmod(seconds, 60 * 60 * 24)
+ hours, seconds = divmod(seconds, 60 * 60)
+ minutes, seconds = divmod(seconds, 60)
+ time_parts = []
+ if years > 0:
+ term = "year(s)"
+ time_parts.append(f"{int(years)} year{'' if years == 1 else 's'}")
+ if months > 0:
+ if term == "minute(s)":
+ term = "month(s)"
+ time_parts.append(f"{int(months)} month{'' if months == 1 else 's'}")
+ if days > 0:
+ if term == "minute(s)":
+ term = "day(s)"
+ time_parts.append(f"{int(days)} day{'' if days == 1 else 's'}")
+ if hours > 0:
+ if term == "minute(s)":
+ term = "hour(s)"
+ time_parts.append(f"{int(hours)} hour{'' if hours == 1 else 's'}")
+ if minutes > 0:
+ time_parts.append(f"{int(minutes)} minute{'' if minutes == 1 else 's'}")
+
+ if len(time_parts) > 1:
+ time_parts[-1] = f"and {time_parts[-1]}"
+
+ return " ".join(time_parts), term
+
+
def path_to_dict(
path: str,
*,
diff --git a/tests/KubernetesTest.py b/tests/KubernetesTest.py
index afbfffe36..a47c1c877 100644
--- a/tests/KubernetesTest.py
+++ b/tests/KubernetesTest.py
@@ -32,7 +32,7 @@ class KubernetesTest(Test):
"USE_PROXY_PROTOCOL": "yes",
"REAL_IP_FROM": "100.64.0.0/10 192.168.0.0/16 172.16.0.0/12 10.0.0.0/8",
"REAL_IP_HEADER": "proxy_protocol",
- "LOG_LEVEL": "info"
+ "LOG_LEVEL": "info",
}
replace_env = {"API_WHITELIST_IP": "127.0.0.1/8 100.64.0.0/10 192.168.0.0/16 172.16.0.0/12 10.0.0.0/8"}
for yaml in data:
diff --git a/tests/core/antibot/Dockerfile b/tests/core/antibot/Dockerfile
index e5e0eeed5..8392c38b5 100644
--- a/tests/core/antibot/Dockerfile
+++ b/tests/core/antibot/Dockerfile
@@ -1,4 +1,4 @@
-FROM python:3.12.1-alpine3.18@sha256:af0d8da43677e3000ebdf4045508d891a87e7bd2d3ec87bc6e40403be97291b8
+FROM python:3.12.1-alpine3.18@sha256:fb759579d60cfe1f70b110a27be95aaa7cf758d2fa21cf54fffb71c2ba3f8034
# Install firefox and geckodriver
RUN apk add --no-cache --virtual .build-deps curl grep zip wget && \
diff --git a/tests/core/antibot/requirements.in b/tests/core/antibot/requirements.in
index 49cb1341f..45ceb3f45 100644
--- a/tests/core/antibot/requirements.in
+++ b/tests/core/antibot/requirements.in
@@ -1,2 +1,2 @@
requests==2.31.0
-selenium==4.16.0
+selenium<4.17.0
diff --git a/tests/core/authbasic/Dockerfile b/tests/core/authbasic/Dockerfile
index e5e0eeed5..8392c38b5 100644
--- a/tests/core/authbasic/Dockerfile
+++ b/tests/core/authbasic/Dockerfile
@@ -1,4 +1,4 @@
-FROM python:3.12.1-alpine3.18@sha256:af0d8da43677e3000ebdf4045508d891a87e7bd2d3ec87bc6e40403be97291b8
+FROM python:3.12.1-alpine3.18@sha256:fb759579d60cfe1f70b110a27be95aaa7cf758d2fa21cf54fffb71c2ba3f8034
# Install firefox and geckodriver
RUN apk add --no-cache --virtual .build-deps curl grep zip wget && \
diff --git a/tests/core/authbasic/requirements.in b/tests/core/authbasic/requirements.in
index 49cb1341f..45ceb3f45 100644
--- a/tests/core/authbasic/requirements.in
+++ b/tests/core/authbasic/requirements.in
@@ -1,2 +1,2 @@
requests==2.31.0
-selenium==4.16.0
+selenium<4.17.0
diff --git a/tests/core/badbehavior/Dockerfile b/tests/core/badbehavior/Dockerfile
index fe3cea3e7..29c73e1f0 100644
--- a/tests/core/badbehavior/Dockerfile
+++ b/tests/core/badbehavior/Dockerfile
@@ -1,4 +1,4 @@
-FROM python:3.12.1-alpine3.18@sha256:af0d8da43677e3000ebdf4045508d891a87e7bd2d3ec87bc6e40403be97291b8
+FROM python:3.12.1-alpine3.18@sha256:fb759579d60cfe1f70b110a27be95aaa7cf758d2fa21cf54fffb71c2ba3f8034
WORKDIR /tmp
diff --git a/tests/core/blacklist/Dockerfile b/tests/core/blacklist/Dockerfile
index fe3cea3e7..29c73e1f0 100644
--- a/tests/core/blacklist/Dockerfile
+++ b/tests/core/blacklist/Dockerfile
@@ -1,4 +1,4 @@
-FROM python:3.12.1-alpine3.18@sha256:af0d8da43677e3000ebdf4045508d891a87e7bd2d3ec87bc6e40403be97291b8
+FROM python:3.12.1-alpine3.18@sha256:fb759579d60cfe1f70b110a27be95aaa7cf758d2fa21cf54fffb71c2ba3f8034
WORKDIR /tmp
diff --git a/tests/core/blacklist/api/Dockerfile b/tests/core/blacklist/api/Dockerfile
index 91a0f42ed..02c9ca639 100644
--- a/tests/core/blacklist/api/Dockerfile
+++ b/tests/core/blacklist/api/Dockerfile
@@ -1,4 +1,4 @@
-FROM python:3.12.1-alpine3.18@sha256:af0d8da43677e3000ebdf4045508d891a87e7bd2d3ec87bc6e40403be97291b8
+FROM python:3.12.1-alpine3.18@sha256:fb759579d60cfe1f70b110a27be95aaa7cf758d2fa21cf54fffb71c2ba3f8034
WORKDIR /tmp
diff --git a/tests/core/blacklist/api/requirements.in b/tests/core/blacklist/api/requirements.in
index c70d8e9ca..01e8a7398 100644
--- a/tests/core/blacklist/api/requirements.in
+++ b/tests/core/blacklist/api/requirements.in
@@ -1,2 +1,2 @@
fastapi==0.109.0
-uvicorn[standard]==0.25.0
+uvicorn[standard]==0.27.0
diff --git a/tests/core/blacklist/api/requirements.txt b/tests/core/blacklist/api/requirements.txt
index 9f6ef8206..f64cba8e6 100644
--- a/tests/core/blacklist/api/requirements.txt
+++ b/tests/core/blacklist/api/requirements.txt
@@ -183,9 +183,9 @@ pydantic-core==2.14.6 \
--hash=sha256:fd9e98b408384989ea4ab60206b8e100d8687da18b5c813c11e92fd8212a98e0 \
--hash=sha256:ffff855100bc066ff2cd3aa4a60bc9534661816b110f0243e59503ec2df38421
# via pydantic
-python-dotenv==1.0.0 \
- --hash=sha256:a8df96034aae6d2d50a4ebe8216326c61c3eb64836776504fcca410e5937a3ba \
- --hash=sha256:f5971a9226b701070a4bf2c38c89e5a3f0d64de8debda981d1db98583009122a
+python-dotenv==1.0.1 \
+ --hash=sha256:e324ee90a023d808f1959c46bcbc04446a10ced277783dc6ee09987c37ec10ca \
+ --hash=sha256:f7b63ef50f1b690dddf550d03497b66d609393b40b564ed0d674909a68ebf16a
# via uvicorn
pyyaml==6.0.1 \
--hash=sha256:04ac92ad1925b2cff1db0cfebffb6ffc43457495c9b3c39d3fcae417d7125dc5 \
@@ -217,6 +217,7 @@ pyyaml==6.0.1 \
--hash=sha256:8d4e9c88387b0f5c7d5f281e55304de64cf7f9c0021a3525bd3b1c542da3b0e4 \
--hash=sha256:9046c58c4395dff28dd494285c82ba00b546adfc7ef001486fbf0324bc174fba \
--hash=sha256:9eb6caa9a297fc2c2fb8862bc5370d0303ddba53ba97e71f08023b6cd73d16a8 \
+ --hash=sha256:a08c6f0fe150303c1c6b71ebcd7213c2858041a7e01975da3a99aed1e7a378ef \
--hash=sha256:a0cd17c15d3bb3fa06978b4e8958dcdc6e0174ccea823003a106c7d4d7899ac5 \
--hash=sha256:afd7e57eddb1a54f0f1a974bc4391af8bcce0b444685d936840f125cf046d5bd \
--hash=sha256:b1275ad35a5d18c62a7220633c913e1b42d44b46ee12554e5fd39c70a243d6a3 \
@@ -257,9 +258,9 @@ typing-extensions==4.9.0 \
# pydantic-core
# starlette
# uvicorn
-uvicorn==0.25.0 \
- --hash=sha256:6dddbad1d7ee0f5140aba5ec138ddc9612c5109399903828b4874c9937f009c2 \
- --hash=sha256:ce107f5d9bd02b4636001a77a4e74aab5e1e2b146868ebbad565237145af444c
+uvicorn==0.27.0 \
+ --hash=sha256:890b00f6c537d58695d3bb1f28e23db9d9e7a17cbcc76d7457c499935f933e24 \
+ --hash=sha256:c855578045d45625fd027367f7653d249f7c49f9361ba15cf9624186b26b8eb6
# via
# -r requirements.in
# uvicorn
diff --git a/tests/core/blacklist/init/Dockerfile b/tests/core/blacklist/init/Dockerfile
index 337a70388..3048b84c5 100644
--- a/tests/core/blacklist/init/Dockerfile
+++ b/tests/core/blacklist/init/Dockerfile
@@ -1,4 +1,4 @@
-FROM python:3.12.1-alpine3.18@sha256:af0d8da43677e3000ebdf4045508d891a87e7bd2d3ec87bc6e40403be97291b8
+FROM python:3.12.1-alpine3.18@sha256:fb759579d60cfe1f70b110a27be95aaa7cf758d2fa21cf54fffb71c2ba3f8034
WORKDIR /tmp
diff --git a/tests/core/brotli/Dockerfile b/tests/core/brotli/Dockerfile
index fe3cea3e7..29c73e1f0 100644
--- a/tests/core/brotli/Dockerfile
+++ b/tests/core/brotli/Dockerfile
@@ -1,4 +1,4 @@
-FROM python:3.12.1-alpine3.18@sha256:af0d8da43677e3000ebdf4045508d891a87e7bd2d3ec87bc6e40403be97291b8
+FROM python:3.12.1-alpine3.18@sha256:fb759579d60cfe1f70b110a27be95aaa7cf758d2fa21cf54fffb71c2ba3f8034
WORKDIR /tmp
diff --git a/tests/core/bunkernet/Dockerfile b/tests/core/bunkernet/Dockerfile
index fe3cea3e7..29c73e1f0 100644
--- a/tests/core/bunkernet/Dockerfile
+++ b/tests/core/bunkernet/Dockerfile
@@ -1,4 +1,4 @@
-FROM python:3.12.1-alpine3.18@sha256:af0d8da43677e3000ebdf4045508d891a87e7bd2d3ec87bc6e40403be97291b8
+FROM python:3.12.1-alpine3.18@sha256:fb759579d60cfe1f70b110a27be95aaa7cf758d2fa21cf54fffb71c2ba3f8034
WORKDIR /tmp
diff --git a/tests/core/bunkernet/api/Dockerfile b/tests/core/bunkernet/api/Dockerfile
index 91a0f42ed..02c9ca639 100644
--- a/tests/core/bunkernet/api/Dockerfile
+++ b/tests/core/bunkernet/api/Dockerfile
@@ -1,4 +1,4 @@
-FROM python:3.12.1-alpine3.18@sha256:af0d8da43677e3000ebdf4045508d891a87e7bd2d3ec87bc6e40403be97291b8
+FROM python:3.12.1-alpine3.18@sha256:fb759579d60cfe1f70b110a27be95aaa7cf758d2fa21cf54fffb71c2ba3f8034
WORKDIR /tmp
diff --git a/tests/core/bunkernet/api/requirements.in b/tests/core/bunkernet/api/requirements.in
index c70d8e9ca..01e8a7398 100644
--- a/tests/core/bunkernet/api/requirements.in
+++ b/tests/core/bunkernet/api/requirements.in
@@ -1,2 +1,2 @@
fastapi==0.109.0
-uvicorn[standard]==0.25.0
+uvicorn[standard]==0.27.0
diff --git a/tests/core/bunkernet/api/requirements.txt b/tests/core/bunkernet/api/requirements.txt
index 9f6ef8206..f64cba8e6 100644
--- a/tests/core/bunkernet/api/requirements.txt
+++ b/tests/core/bunkernet/api/requirements.txt
@@ -183,9 +183,9 @@ pydantic-core==2.14.6 \
--hash=sha256:fd9e98b408384989ea4ab60206b8e100d8687da18b5c813c11e92fd8212a98e0 \
--hash=sha256:ffff855100bc066ff2cd3aa4a60bc9534661816b110f0243e59503ec2df38421
# via pydantic
-python-dotenv==1.0.0 \
- --hash=sha256:a8df96034aae6d2d50a4ebe8216326c61c3eb64836776504fcca410e5937a3ba \
- --hash=sha256:f5971a9226b701070a4bf2c38c89e5a3f0d64de8debda981d1db98583009122a
+python-dotenv==1.0.1 \
+ --hash=sha256:e324ee90a023d808f1959c46bcbc04446a10ced277783dc6ee09987c37ec10ca \
+ --hash=sha256:f7b63ef50f1b690dddf550d03497b66d609393b40b564ed0d674909a68ebf16a
# via uvicorn
pyyaml==6.0.1 \
--hash=sha256:04ac92ad1925b2cff1db0cfebffb6ffc43457495c9b3c39d3fcae417d7125dc5 \
@@ -217,6 +217,7 @@ pyyaml==6.0.1 \
--hash=sha256:8d4e9c88387b0f5c7d5f281e55304de64cf7f9c0021a3525bd3b1c542da3b0e4 \
--hash=sha256:9046c58c4395dff28dd494285c82ba00b546adfc7ef001486fbf0324bc174fba \
--hash=sha256:9eb6caa9a297fc2c2fb8862bc5370d0303ddba53ba97e71f08023b6cd73d16a8 \
+ --hash=sha256:a08c6f0fe150303c1c6b71ebcd7213c2858041a7e01975da3a99aed1e7a378ef \
--hash=sha256:a0cd17c15d3bb3fa06978b4e8958dcdc6e0174ccea823003a106c7d4d7899ac5 \
--hash=sha256:afd7e57eddb1a54f0f1a974bc4391af8bcce0b444685d936840f125cf046d5bd \
--hash=sha256:b1275ad35a5d18c62a7220633c913e1b42d44b46ee12554e5fd39c70a243d6a3 \
@@ -257,9 +258,9 @@ typing-extensions==4.9.0 \
# pydantic-core
# starlette
# uvicorn
-uvicorn==0.25.0 \
- --hash=sha256:6dddbad1d7ee0f5140aba5ec138ddc9612c5109399903828b4874c9937f009c2 \
- --hash=sha256:ce107f5d9bd02b4636001a77a4e74aab5e1e2b146868ebbad565237145af444c
+uvicorn==0.27.0 \
+ --hash=sha256:890b00f6c537d58695d3bb1f28e23db9d9e7a17cbcc76d7457c499935f933e24 \
+ --hash=sha256:c855578045d45625fd027367f7653d249f7c49f9361ba15cf9624186b26b8eb6
# via
# -r requirements.in
# uvicorn
diff --git a/tests/core/bwcli/Dockerfile b/tests/core/bwcli/Dockerfile
index fe3cea3e7..29c73e1f0 100644
--- a/tests/core/bwcli/Dockerfile
+++ b/tests/core/bwcli/Dockerfile
@@ -1,4 +1,4 @@
-FROM python:3.12.1-alpine3.18@sha256:af0d8da43677e3000ebdf4045508d891a87e7bd2d3ec87bc6e40403be97291b8
+FROM python:3.12.1-alpine3.18@sha256:fb759579d60cfe1f70b110a27be95aaa7cf758d2fa21cf54fffb71c2ba3f8034
WORKDIR /tmp
diff --git a/tests/core/clientcache/Dockerfile b/tests/core/clientcache/Dockerfile
index fe3cea3e7..29c73e1f0 100644
--- a/tests/core/clientcache/Dockerfile
+++ b/tests/core/clientcache/Dockerfile
@@ -1,4 +1,4 @@
-FROM python:3.12.1-alpine3.18@sha256:af0d8da43677e3000ebdf4045508d891a87e7bd2d3ec87bc6e40403be97291b8
+FROM python:3.12.1-alpine3.18@sha256:fb759579d60cfe1f70b110a27be95aaa7cf758d2fa21cf54fffb71c2ba3f8034
WORKDIR /tmp
diff --git a/tests/core/cors/Dockerfile b/tests/core/cors/Dockerfile
index e5e0eeed5..8392c38b5 100644
--- a/tests/core/cors/Dockerfile
+++ b/tests/core/cors/Dockerfile
@@ -1,4 +1,4 @@
-FROM python:3.12.1-alpine3.18@sha256:af0d8da43677e3000ebdf4045508d891a87e7bd2d3ec87bc6e40403be97291b8
+FROM python:3.12.1-alpine3.18@sha256:fb759579d60cfe1f70b110a27be95aaa7cf758d2fa21cf54fffb71c2ba3f8034
# Install firefox and geckodriver
RUN apk add --no-cache --virtual .build-deps curl grep zip wget && \
diff --git a/tests/core/cors/Dockerfile.init b/tests/core/cors/Dockerfile.init
index 7571ef111..d5093eae1 100644
--- a/tests/core/cors/Dockerfile.init
+++ b/tests/core/cors/Dockerfile.init
@@ -1,4 +1,4 @@
-FROM alpine:3.18@sha256:48d9183eb12a05c99bcc0bf44a003607b8e941e1d4f41f9ad12bdcc4b5672f86
+FROM alpine:3.18@sha256:34871e7290500828b39e22294660bee86d966bc0017544e848dd9a255cdf59e0
WORKDIR /opt/init
diff --git a/tests/core/cors/requirements.in b/tests/core/cors/requirements.in
index 49cb1341f..45ceb3f45 100644
--- a/tests/core/cors/requirements.in
+++ b/tests/core/cors/requirements.in
@@ -1,2 +1,2 @@
requests==2.31.0
-selenium==4.16.0
+selenium<4.17.0
diff --git a/tests/core/country/Dockerfile b/tests/core/country/Dockerfile
index fe3cea3e7..29c73e1f0 100644
--- a/tests/core/country/Dockerfile
+++ b/tests/core/country/Dockerfile
@@ -1,4 +1,4 @@
-FROM python:3.12.1-alpine3.18@sha256:af0d8da43677e3000ebdf4045508d891a87e7bd2d3ec87bc6e40403be97291b8
+FROM python:3.12.1-alpine3.18@sha256:fb759579d60cfe1f70b110a27be95aaa7cf758d2fa21cf54fffb71c2ba3f8034
WORKDIR /tmp
diff --git a/tests/core/customcert/Dockerfile b/tests/core/customcert/Dockerfile
index fe3cea3e7..29c73e1f0 100644
--- a/tests/core/customcert/Dockerfile
+++ b/tests/core/customcert/Dockerfile
@@ -1,4 +1,4 @@
-FROM python:3.12.1-alpine3.18@sha256:af0d8da43677e3000ebdf4045508d891a87e7bd2d3ec87bc6e40403be97291b8
+FROM python:3.12.1-alpine3.18@sha256:fb759579d60cfe1f70b110a27be95aaa7cf758d2fa21cf54fffb71c2ba3f8034
WORKDIR /tmp
diff --git a/tests/core/customcert/docker-compose.test.yml b/tests/core/customcert/docker-compose.test.yml
index b487d2288..c64ff47ef 100644
--- a/tests/core/customcert/docker-compose.test.yml
+++ b/tests/core/customcert/docker-compose.test.yml
@@ -6,8 +6,9 @@ services:
environment:
PYTHONUNBUFFERED: "1"
USE_CUSTOM_SSL: "no"
+ CUSTOM_SSL_CERT: "/certs/certificate.pem"
extra_hosts:
- - "www.example.com:192.168.0.2"
+ - "app1.example.com:192.168.0.2"
networks:
bw-services:
ipv4_address: 192.168.0.3
diff --git a/tests/core/customcert/docker-compose.yml b/tests/core/customcert/docker-compose.yml
index be9363f5a..2fdacee71 100644
--- a/tests/core/customcert/docker-compose.yml
+++ b/tests/core/customcert/docker-compose.yml
@@ -2,13 +2,17 @@ version: "3.5"
services:
bw:
- image: bunkerity/bunkerweb:1.5.5
- pull_policy: never
+ # image: bunkerity/bunkerweb:1.5.5
+ # pull_policy: never
+ build:
+ context: ../../..
+ dockerfile: src/bw/Dockerfile
labels:
- "bunkerweb.INSTANCE=yes"
volumes:
- ./index.html:/var/www/html/index.html
environment:
+ SERVER_NAME: "app1.example.com"
API_WHITELIST_IP: "127.0.0.0/8 10.20.30.0/24 192.168.0.3"
HTTP_PORT: "80"
HTTPS_PORT: "443"
@@ -36,8 +40,11 @@ services:
ipv4_address: 192.168.0.2
bw-scheduler:
- image: bunkerity/bunkerweb-scheduler:1.5.5
- pull_policy: never
+ # image: bunkerity/bunkerweb-scheduler:1.5.5
+ # pull_policy: never
+ build:
+ context: ../../..
+ dockerfile: src/scheduler/Dockerfile
depends_on:
- bw
- bw-docker
diff --git a/tests/core/customcert/init/entrypoint.sh b/tests/core/customcert/init/entrypoint.sh
index 87a2aca12..0d2bba548 100644
--- a/tests/core/customcert/init/entrypoint.sh
+++ b/tests/core/customcert/init/entrypoint.sh
@@ -1,7 +1,7 @@
#!/bin/bash
-echo "ℹ️ Generating certificate for www.example.com ..."
-openssl req -nodes -x509 -newkey rsa:4096 -keyout /certs/privatekey.key -out /certs/certificate.pem -days 365 -subj /CN=www.example.com/
+echo "ℹ️ Generating certificate for app1.example.com ..."
+openssl req -nodes -x509 -newkey rsa:4096 -keyout /certs/privatekey.key -out /certs/certificate.pem -days 365 -subj /CN=app1.example.com/
chown -R root:101 /certs
chmod -R 777 /certs
diff --git a/tests/core/customcert/main.py b/tests/core/customcert/main.py
index 1dae50d7a..58b64324f 100644
--- a/tests/core/customcert/main.py
+++ b/tests/core/customcert/main.py
@@ -1,5 +1,9 @@
from contextlib import suppress
+from cryptography import x509
+from cryptography.hazmat.backends import default_backend
from os import getenv
+from socket import create_connection
+from ssl import CERT_NONE, DER_cert_to_PEM_cert, create_default_context
from requests import RequestException, get
from traceback import format_exc
from time import sleep
@@ -9,7 +13,7 @@ try:
retries = 0
while not ready:
with suppress(RequestException):
- resp = get("http://www.example.com/ready", headers={"Host": "www.example.com"}, verify=False, allow_redirects=True)
+ resp = get("http://app1.example.com/ready", headers={"Host": "app1.example.com"}, verify=False, allow_redirects=True)
status_code = resp.status_code
text = resp.text
@@ -28,14 +32,16 @@ try:
sleep(5)
use_custom_ssl = getenv("USE_CUSTOM_SSL", "no") == "yes"
+ fallback = not bool(getenv("CUSTOM_SSL_CERT", False))
print(
- "ℹ️ Sending a request to http://www.example.com ...",
+ "ℹ️ Sending a request to http://app1.example.com ...",
flush=True,
)
try:
- get("http://www.example.com", headers={"Host": "www.example.com"})
+ req = get("http://app1.example.com", headers={"Host": "app1.example.com"})
+ req.raise_for_status()
except RequestException:
if not use_custom_ssl:
print(
@@ -49,20 +55,48 @@ try:
exit(0)
print(
- "ℹ️ Sending a request to https://www.example.com ...",
+ "ℹ️ Sending a request to https://app1.example.com ...",
flush=True,
)
try:
- get("https://www.example.com", headers={"Host": "www.example.com"}, verify=False)
- except RequestException:
+ req = get("https://app1.example.com", headers={"Host": "app1.example.com"}, verify=False)
+ req.raise_for_status()
+ except RequestException as e:
print(
- "❌ The request failed even though the Custom Cert is activated, exiting ...",
+ f"❌ The request failed even though the Custom Cert is activated:\n{e}\n exiting ...",
flush=True,
)
exit(1)
- print("✅ The Custom Cert is activated, as expected ...", flush=True)
+ sleep(1)
+
+ context = create_default_context()
+ context.check_hostname = False
+ context.verify_mode = CERT_NONE
+ with create_connection(("app1.example.com", 443)) as sock:
+ with context.wrap_socket(sock, server_hostname="app1.example.com") as ssock:
+ # Retrieve the SSL certificate
+ pem_data = DER_cert_to_PEM_cert(ssock.getpeercert(True))
+
+ # Parse the PEM certificate
+ certificate = x509.load_pem_x509_certificate(pem_data.encode(), default_backend())
+
+ common_name = certificate.subject.get_attributes_for_oid(x509.oid.NameOID.COMMON_NAME)[0].value
+ if fallback and common_name != "www.example.org":
+ print(
+ f"❌ The Custom Cert is activated and the Common Name (CN) is not www.example.org (fallback one) but {common_name}, exiting ...",
+ flush=True,
+ )
+ exit(1)
+ elif not fallback and common_name != "app1.example.com":
+ print(
+ f"❌ The Custom Cert is activated and the Common Name (CN) is not app1.example.com but {common_name}, exiting ...",
+ flush=True,
+ )
+ exit(1)
+
+ print("✅ The Custom Cert is activated and the Common Name (CN) is the right one, as expected ...", flush=True)
except SystemExit as e:
exit(e.code)
except:
diff --git a/tests/core/customcert/requirements.in b/tests/core/customcert/requirements.in
index 49cb1341f..2b08c8e7b 100644
--- a/tests/core/customcert/requirements.in
+++ b/tests/core/customcert/requirements.in
@@ -1,2 +1,3 @@
+cryptography==42.0.0
requests==2.31.0
-selenium==4.16.0
+selenium<4.17.0
diff --git a/tests/core/customcert/requirements.txt b/tests/core/customcert/requirements.txt
index 7dc9efbe9..913434c4c 100644
--- a/tests/core/customcert/requirements.txt
+++ b/tests/core/customcert/requirements.txt
@@ -16,6 +16,60 @@ certifi==2023.11.17 \
# via
# requests
# selenium
+cffi==1.16.0 \
+ --hash=sha256:0c9ef6ff37e974b73c25eecc13952c55bceed9112be2d9d938ded8e856138bcc \
+ --hash=sha256:131fd094d1065b19540c3d72594260f118b231090295d8c34e19a7bbcf2e860a \
+ --hash=sha256:1b8ebc27c014c59692bb2664c7d13ce7a6e9a629be20e54e7271fa696ff2b417 \
+ --hash=sha256:2c56b361916f390cd758a57f2e16233eb4f64bcbeee88a4881ea90fca14dc6ab \
+ --hash=sha256:2d92b25dbf6cae33f65005baf472d2c245c050b1ce709cc4588cdcdd5495b520 \
+ --hash=sha256:31d13b0f99e0836b7ff893d37af07366ebc90b678b6664c955b54561fc36ef36 \
+ --hash=sha256:32c68ef735dbe5857c810328cb2481e24722a59a2003018885514d4c09af9743 \
+ --hash=sha256:3686dffb02459559c74dd3d81748269ffb0eb027c39a6fc99502de37d501faa8 \
+ --hash=sha256:582215a0e9adbe0e379761260553ba11c58943e4bbe9c36430c4ca6ac74b15ed \
+ --hash=sha256:5b50bf3f55561dac5438f8e70bfcdfd74543fd60df5fa5f62d94e5867deca684 \
+ --hash=sha256:5bf44d66cdf9e893637896c7faa22298baebcd18d1ddb6d2626a6e39793a1d56 \
+ --hash=sha256:6602bc8dc6f3a9e02b6c22c4fc1e47aa50f8f8e6d3f78a5e16ac33ef5fefa324 \
+ --hash=sha256:673739cb539f8cdaa07d92d02efa93c9ccf87e345b9a0b556e3ecc666718468d \
+ --hash=sha256:68678abf380b42ce21a5f2abde8efee05c114c2fdb2e9eef2efdb0257fba1235 \
+ --hash=sha256:68e7c44931cc171c54ccb702482e9fc723192e88d25a0e133edd7aff8fcd1f6e \
+ --hash=sha256:6b3d6606d369fc1da4fd8c357d026317fbb9c9b75d36dc16e90e84c26854b088 \
+ --hash=sha256:748dcd1e3d3d7cd5443ef03ce8685043294ad6bd7c02a38d1bd367cfd968e000 \
+ --hash=sha256:7651c50c8c5ef7bdb41108b7b8c5a83013bfaa8a935590c5d74627c047a583c7 \
+ --hash=sha256:7b78010e7b97fef4bee1e896df8a4bbb6712b7f05b7ef630f9d1da00f6444d2e \
+ --hash=sha256:7e61e3e4fa664a8588aa25c883eab612a188c725755afff6289454d6362b9673 \
+ --hash=sha256:80876338e19c951fdfed6198e70bc88f1c9758b94578d5a7c4c91a87af3cf31c \
+ --hash=sha256:8895613bcc094d4a1b2dbe179d88d7fb4a15cee43c052e8885783fac397d91fe \
+ --hash=sha256:88e2b3c14bdb32e440be531ade29d3c50a1a59cd4e51b1dd8b0865c54ea5d2e2 \
+ --hash=sha256:8f8e709127c6c77446a8c0a8c8bf3c8ee706a06cd44b1e827c3e6a2ee6b8c098 \
+ --hash=sha256:9cb4a35b3642fc5c005a6755a5d17c6c8b6bcb6981baf81cea8bfbc8903e8ba8 \
+ --hash=sha256:9f90389693731ff1f659e55c7d1640e2ec43ff725cc61b04b2f9c6d8d017df6a \
+ --hash=sha256:a09582f178759ee8128d9270cd1344154fd473bb77d94ce0aeb2a93ebf0feaf0 \
+ --hash=sha256:a6a14b17d7e17fa0d207ac08642c8820f84f25ce17a442fd15e27ea18d67c59b \
+ --hash=sha256:a72e8961a86d19bdb45851d8f1f08b041ea37d2bd8d4fd19903bc3083d80c896 \
+ --hash=sha256:abd808f9c129ba2beda4cfc53bde801e5bcf9d6e0f22f095e45327c038bfe68e \
+ --hash=sha256:ac0f5edd2360eea2f1daa9e26a41db02dd4b0451b48f7c318e217ee092a213e9 \
+ --hash=sha256:b29ebffcf550f9da55bec9e02ad430c992a87e5f512cd63388abb76f1036d8d2 \
+ --hash=sha256:b2ca4e77f9f47c55c194982e10f058db063937845bb2b7a86c84a6cfe0aefa8b \
+ --hash=sha256:b7be2d771cdba2942e13215c4e340bfd76398e9227ad10402a8767ab1865d2e6 \
+ --hash=sha256:b84834d0cf97e7d27dd5b7f3aca7b6e9263c56308ab9dc8aae9784abb774d404 \
+ --hash=sha256:b86851a328eedc692acf81fb05444bdf1891747c25af7529e39ddafaf68a4f3f \
+ --hash=sha256:bcb3ef43e58665bbda2fb198698fcae6776483e0c4a631aa5647806c25e02cc0 \
+ --hash=sha256:c0f31130ebc2d37cdd8e44605fb5fa7ad59049298b3f745c74fa74c62fbfcfc4 \
+ --hash=sha256:c6a164aa47843fb1b01e941d385aab7215563bb8816d80ff3a363a9f8448a8dc \
+ --hash=sha256:d8a9d3ebe49f084ad71f9269834ceccbf398253c9fac910c4fd7053ff1386936 \
+ --hash=sha256:db8e577c19c0fda0beb7e0d4e09e0ba74b1e4c092e0e40bfa12fe05b6f6d75ba \
+ --hash=sha256:dc9b18bf40cc75f66f40a7379f6a9513244fe33c0e8aa72e2d56b0196a7ef872 \
+ --hash=sha256:e09f3ff613345df5e8c3667da1d918f9149bd623cd9070c983c013792a9a62eb \
+ --hash=sha256:e4108df7fe9b707191e55f33efbcb2d81928e10cea45527879a4749cbe472614 \
+ --hash=sha256:e6024675e67af929088fda399b2094574609396b1decb609c55fa58b028a32a1 \
+ --hash=sha256:e70f54f1796669ef691ca07d046cd81a29cb4deb1e5f942003f401c0c4a2695d \
+ --hash=sha256:e715596e683d2ce000574bae5d07bd522c781a822866c20495e52520564f0969 \
+ --hash=sha256:e760191dd42581e023a68b758769e2da259b5d52e3103c6060ddc02c9edb8d7b \
+ --hash=sha256:ed86a35631f7bfbb28e108dd96773b9d5a6ce4811cf6ea468bb6a359b256b1e4 \
+ --hash=sha256:ee07e47c12890ef248766a6e55bd38ebfb2bb8edd4142d56db91b21ea68b7627 \
+ --hash=sha256:fa3a0128b152627161ce47201262d3140edb5a5c3da88d73a1b790a959126956 \
+ --hash=sha256:fcc8eb6d5902bb1cf6dc4f187ee3ea80a1eba0a89aba40a5cb20a5087d961357
+ # via cryptography
charset-normalizer==3.3.2 \
--hash=sha256:06435b539f889b1f6f4ac1758871aae42dc3a8c0e24ac9e60c2384973ad73027 \
--hash=sha256:06a81e93cd441c56a9b65d8e1d043daeb97a3d0856d177d5c90ba85acb3db087 \
@@ -108,6 +162,40 @@ charset-normalizer==3.3.2 \
--hash=sha256:fd1abc0d89e30cc4e02e4064dc67fcc51bd941eb395c502aac3ec19fab46b519 \
--hash=sha256:ff8fa367d09b717b2a17a052544193ad76cd49979c805768879cb63d9ca50561
# via requests
+cryptography==42.0.0 \
+ --hash=sha256:0a68bfcf57a6887818307600c3c0ebc3f62fbb6ccad2240aa21887cda1f8df1b \
+ --hash=sha256:146e971e92a6dd042214b537a726c9750496128453146ab0ee8971a0299dc9bd \
+ --hash=sha256:14e4b909373bc5bf1095311fa0f7fcabf2d1a160ca13f1e9e467be1ac4cbdf94 \
+ --hash=sha256:206aaf42e031b93f86ad60f9f5d9da1b09164f25488238ac1dc488334eb5e221 \
+ --hash=sha256:3005166a39b70c8b94455fdbe78d87a444da31ff70de3331cdec2c568cf25b7e \
+ --hash=sha256:324721d93b998cb7367f1e6897370644751e5580ff9b370c0a50dc60a2003513 \
+ --hash=sha256:33588310b5c886dfb87dba5f013b8d27df7ffd31dc753775342a1e5ab139e59d \
+ --hash=sha256:35cf6ed4c38f054478a9df14f03c1169bb14bd98f0b1705751079b25e1cb58bc \
+ --hash=sha256:3ca482ea80626048975360c8e62be3ceb0f11803180b73163acd24bf014133a0 \
+ --hash=sha256:56ce0c106d5c3fec1038c3cca3d55ac320a5be1b44bf15116732d0bc716979a2 \
+ --hash=sha256:5a217bca51f3b91971400890905a9323ad805838ca3fa1e202a01844f485ee87 \
+ --hash=sha256:678cfa0d1e72ef41d48993a7be75a76b0725d29b820ff3cfd606a5b2b33fda01 \
+ --hash=sha256:69fd009a325cad6fbfd5b04c711a4da563c6c4854fc4c9544bff3088387c77c0 \
+ --hash=sha256:6cf9b76d6e93c62114bd19485e5cb003115c134cf9ce91f8ac924c44f8c8c3f4 \
+ --hash=sha256:74f18a4c8ca04134d2052a140322002fef535c99cdbc2a6afc18a8024d5c9d5b \
+ --hash=sha256:85f759ed59ffd1d0baad296e72780aa62ff8a71f94dc1ab340386a1207d0ea81 \
+ --hash=sha256:87086eae86a700307b544625e3ba11cc600c3c0ef8ab97b0fda0705d6db3d4e3 \
+ --hash=sha256:8814722cffcfd1fbd91edd9f3451b88a8f26a5fd41b28c1c9193949d1c689dc4 \
+ --hash=sha256:8fedec73d590fd30c4e3f0d0f4bc961aeca8390c72f3eaa1a0874d180e868ddf \
+ --hash=sha256:9515ea7f596c8092fdc9902627e51b23a75daa2c7815ed5aa8cf4f07469212ec \
+ --hash=sha256:988b738f56c665366b1e4bfd9045c3efae89ee366ca3839cd5af53eaa1401bce \
+ --hash=sha256:a2a8d873667e4fd2f34aedab02ba500b824692c6542e017075a2efc38f60a4c0 \
+ --hash=sha256:bd7cf7a8d9f34cc67220f1195884151426ce616fdc8285df9054bfa10135925f \
+ --hash=sha256:bdce70e562c69bb089523e75ef1d9625b7417c6297a76ac27b1b8b1eb51b7d0f \
+ --hash=sha256:be14b31eb3a293fc6e6aa2807c8a3224c71426f7c4e3639ccf1a2f3ffd6df8c3 \
+ --hash=sha256:be41b0c7366e5549265adf2145135dca107718fa44b6e418dc7499cfff6b4689 \
+ --hash=sha256:c310767268d88803b653fffe6d6f2f17bb9d49ffceb8d70aed50ad45ea49ab08 \
+ --hash=sha256:c58115384bdcfe9c7f644c72f10f6f42bed7cf59f7b52fe1bf7ae0a622b3a139 \
+ --hash=sha256:c640b0ef54138fde761ec99a6c7dc4ce05e80420262c20fa239e694ca371d434 \
+ --hash=sha256:ca20550bb590db16223eb9ccc5852335b48b8f597e2f6f0878bbfd9e7314eb17 \
+ --hash=sha256:d97aae66b7de41cdf5b12087b5509e4e9805ed6f562406dfcf60e8481a9a28f8 \
+ --hash=sha256:e9326ca78111e4c645f7e49cbce4ed2f3f85e17b61a563328c85a5208cf34440
+ # via -r requirements.in
exceptiongroup==1.2.0 \
--hash=sha256:4bfd3996ac73b41e9b9628b04e079f193850720ea5945fc96a08633c66912f14 \
--hash=sha256:91f5c769735f051a4290d52edd0858999b57e5876e9f85937691bd4c9fa3ed68
@@ -128,6 +216,10 @@ outcome==1.3.0.post0 \
--hash=sha256:9dcf02e65f2971b80047b377468e72a268e15c0af3cf1238e6ff14f7f91143b8 \
--hash=sha256:e771c5ce06d1415e356078d3bdd68523f284b4ce5419828922b6871e65eda82b
# via trio
+pycparser==2.21 \
+ --hash=sha256:8ee45429555515e1f6b185e78100aea234072576aa43ab53aefcae078162fca9 \
+ --hash=sha256:e644fdec12f7872f86c58ff790da456218b10f863970249516d60a5eaca77206
+ # via cffi
pysocks==1.7.1 \
--hash=sha256:08e69f092cc6dbe92a0fdd16eeb9b9ffbc13cadfe5ca4c7bd92ffb078b293299 \
--hash=sha256:2725bd0a9925919b9b51739eea5f9e2bae91e83288108a9ad338b2e3a4435ee5 \
diff --git a/tests/core/customcert/test.sh b/tests/core/customcert/test.sh
index 4ebd49da6..ac0e6c363 100755
--- a/tests/core/customcert/test.sh
+++ b/tests/core/customcert/test.sh
@@ -28,9 +28,12 @@ if [ "$integration" == "docker" ] ; then
fi
else
sudo systemctl stop bunkerweb
+ sudo sed -i 's@SERVER_NAME=.*$@SERVER_NAME=app1.example.com@' /etc/bunkerweb/variables.env
echo "USE_CUSTOM_SSL=no" | sudo tee -a /etc/bunkerweb/variables.env
echo "CUSTOM_SSL_CERT=/tmp/certificate.pem" | sudo tee -a /etc/bunkerweb/variables.env
echo "CUSTOM_SSL_KEY=/tmp/privatekey.key" | sudo tee -a /etc/bunkerweb/variables.env
+ export CUSTOM_SSL_CERT="/tmp/certificate.pem"
+ export CUSTOM_SSL_KEY="/tmp/privatekey.key"
sudo touch /var/www/html/index.html
sudo cp ready.conf /etc/bunkerweb/configs/server-http
fi
@@ -43,9 +46,15 @@ cleanup_stack () {
if [ "$integration" == "docker" ] ; then
rm -rf init/certs
find . -type f -name 'docker-compose.*' -exec sed -i 's@USE_CUSTOM_SSL: "yes"@USE_CUSTOM_SSL: "no"@' {} \;
+ find . -type f -name 'docker-compose.*' -exec sed -i 's@CUSTOM_SSL_CERT: ".*"@CUSTOM_SSL_CERT: "/certs/certificate.pem"@' {} \;
+ find . -type f -name 'docker-compose.*' -exec sed -i 's@CUSTOM_SSL_KEY: ".*"@CUSTOM_SSL_KEY: "/certs/privatekey.key"@' {} \;
else
sudo rm -f /tmp/certificate.pem /tmp/privatekey.key
+ sudo sed -i 's@SERVER_NAME=.*$@SERVER_NAME=www.example.com@' /etc/bunkerweb/variables.env
sudo sed -i 's@USE_CUSTOM_SSL=.*$@USE_CUSTOM_SSL=no@' /etc/bunkerweb/variables.env
+ sudo sed -i '$ d' /etc/bunkerweb/variables.env
+ sudo sed -i '$ d' /etc/bunkerweb/variables.env
+ sudo sed -i '$ d' /etc/bunkerweb/variables.env
unset USE_CUSTOM_SSL
unset CUSTOM_SSL_CERT
unset CUSTOM_SSL_KEY
@@ -93,8 +102,8 @@ if [ "$integration" == "docker" ] ; then
exit 1
fi
else
- echo "🔏 Generating certificate for www.example.com ..."
- openssl req -nodes -x509 -newkey rsa:4096 -keyout /tmp/privatekey.key -out /tmp/certificate.pem -days 365 -subj /CN=www.example.com/
+ echo "🔏 Generating certificate for app1.example.com ..."
+ openssl req -nodes -x509 -newkey rsa:4096 -keyout /tmp/privatekey.key -out /tmp/certificate.pem -days 365 -subj /CN=app1.example.com/
# shellcheck disable=SC2181
if [ $? -ne 0 ] ; then
echo "🔏 Certificate generation failed ❌"
@@ -103,7 +112,7 @@ else
sudo chmod 777 /tmp/privatekey.key /tmp/certificate.pem
fi
-for test in "deactivated" "activated"
+for test in "deactivated" "activated" "fallback"
do
if [ "$test" = "deactivated" ] ; then
echo "🔏 Running tests without the custom cert ..."
@@ -115,6 +124,18 @@ do
sudo sed -i 's@USE_CUSTOM_SSL=.*$@USE_CUSTOM_SSL=yes@' /etc/bunkerweb/variables.env
export USE_CUSTOM_SSL="yes"
fi
+ elif [ "$test" = "fallback" ] ; then
+ echo "🔏 Running tests with the custom cert activated and fallback to default cert ..."
+ echo "ℹ Keeping the USE_CUSTOM_SSL variable to yes"
+ if [ "$integration" == "docker" ] ; then
+ find . -type f -name 'docker-compose.*' -exec sed -i 's@CUSTOM_SSL_CERT: ".*"@CUSTOM_SSL_CERT: ""@' {} \;
+ find . -type f -name 'docker-compose.*' -exec sed -i 's@CUSTOM_SSL_KEY: ".*"@CUSTOM_SSL_KEY: ""@' {} \;
+ else
+ sudo sed -i 's@CUSTOM_SSL_CERT=.*$@CUSTOM_SSL_CERT=@' /etc/bunkerweb/variables.env
+ sudo sed -i 's@CUSTOM_SSL_KEY=.*$@CUSTOM_SSL_KEY=@' /etc/bunkerweb/variables.env
+ unset CUSTOM_SSL_CERT
+ unset CUSTOM_SSL_KEY
+ fi
fi
echo "🔏 Starting stack ..."
diff --git a/tests/core/db/Dockerfile b/tests/core/db/Dockerfile
index 0ccd03dd1..2d36e0c0a 100644
--- a/tests/core/db/Dockerfile
+++ b/tests/core/db/Dockerfile
@@ -1,4 +1,4 @@
-FROM python:3.12.1-alpine3.18@sha256:af0d8da43677e3000ebdf4045508d891a87e7bd2d3ec87bc6e40403be97291b8
+FROM python:3.12.1-alpine3.18@sha256:fb759579d60cfe1f70b110a27be95aaa7cf758d2fa21cf54fffb71c2ba3f8034
WORKDIR /tmp
diff --git a/tests/core/db/requirements.in b/tests/core/db/requirements.in
index d1975bf13..485e404cd 100644
--- a/tests/core/db/requirements.in
+++ b/tests/core/db/requirements.in
@@ -1,4 +1,4 @@
-cryptography==41.0.7
-psycopg2-binary==2.9.9
+cryptography==42.0.0
+psycopg[binary,pool]==3.1.17
PyMySQL==1.1.0
sqlalchemy==2.0.25
diff --git a/tests/core/db/requirements.txt b/tests/core/db/requirements.txt
index 38958f334..3d1fb8c84 100644
--- a/tests/core/db/requirements.txt
+++ b/tests/core/db/requirements.txt
@@ -58,30 +58,39 @@ cffi==1.16.0 \
--hash=sha256:fa3a0128b152627161ce47201262d3140edb5a5c3da88d73a1b790a959126956 \
--hash=sha256:fcc8eb6d5902bb1cf6dc4f187ee3ea80a1eba0a89aba40a5cb20a5087d961357
# via cryptography
-cryptography==41.0.7 \
- --hash=sha256:079b85658ea2f59c4f43b70f8119a52414cdb7be34da5d019a77bf96d473b960 \
- --hash=sha256:09616eeaef406f99046553b8a40fbf8b1e70795a91885ba4c96a70793de5504a \
- --hash=sha256:13f93ce9bea8016c253b34afc6bd6a75993e5c40672ed5405a9c832f0d4a00bc \
- --hash=sha256:37a138589b12069efb424220bf78eac59ca68b95696fc622b6ccc1c0a197204a \
- --hash=sha256:3c78451b78313fa81607fa1b3f1ae0a5ddd8014c38a02d9db0616133987b9cdf \
- --hash=sha256:43f2552a2378b44869fe8827aa19e69512e3245a219104438692385b0ee119d1 \
- --hash=sha256:48a0476626da912a44cc078f9893f292f0b3e4c739caf289268168d8f4702a39 \
- --hash=sha256:49f0805fc0b2ac8d4882dd52f4a3b935b210935d500b6b805f321addc8177406 \
- --hash=sha256:5429ec739a29df2e29e15d082f1d9ad683701f0ec7709ca479b3ff2708dae65a \
- --hash=sha256:5a1b41bc97f1ad230a41657d9155113c7521953869ae57ac39ac7f1bb471469a \
- --hash=sha256:68a2dec79deebc5d26d617bfdf6e8aab065a4f34934b22d3b5010df3ba36612c \
- --hash=sha256:7a698cb1dac82c35fcf8fe3417a3aaba97de16a01ac914b89a0889d364d2f6be \
- --hash=sha256:841df4caa01008bad253bce2a6f7b47f86dc9f08df4b433c404def869f590a15 \
- --hash=sha256:90452ba79b8788fa380dfb587cca692976ef4e757b194b093d845e8d99f612f2 \
- --hash=sha256:928258ba5d6f8ae644e764d0f996d61a8777559f72dfeb2eea7e2fe0ad6e782d \
- --hash=sha256:af03b32695b24d85a75d40e1ba39ffe7db7ffcb099fe507b39fd41a565f1b157 \
- --hash=sha256:b640981bf64a3e978a56167594a0e97db71c89a479da8e175d8bb5be5178c003 \
- --hash=sha256:c5ca78485a255e03c32b513f8c2bc39fedb7f5c5f8535545bdc223a03b24f248 \
- --hash=sha256:c7f3201ec47d5207841402594f1d7950879ef890c0c495052fa62f58283fde1a \
- --hash=sha256:d5ec85080cce7b0513cfd233914eb8b7bbd0633f1d1703aa28d1dd5a72f678ec \
- --hash=sha256:d6c391c021ab1f7a82da5d8d0b3cee2f4b2c455ec86c8aebbc84837a631ff309 \
- --hash=sha256:e3114da6d7f95d2dee7d3f4eec16dacff819740bbab931aff8648cb13c5ff5e7 \
- --hash=sha256:f983596065a18a2183e7f79ab3fd4c475205b839e02cbc0efbbf9666c4b3083d
+cryptography==42.0.0 \
+ --hash=sha256:0a68bfcf57a6887818307600c3c0ebc3f62fbb6ccad2240aa21887cda1f8df1b \
+ --hash=sha256:146e971e92a6dd042214b537a726c9750496128453146ab0ee8971a0299dc9bd \
+ --hash=sha256:14e4b909373bc5bf1095311fa0f7fcabf2d1a160ca13f1e9e467be1ac4cbdf94 \
+ --hash=sha256:206aaf42e031b93f86ad60f9f5d9da1b09164f25488238ac1dc488334eb5e221 \
+ --hash=sha256:3005166a39b70c8b94455fdbe78d87a444da31ff70de3331cdec2c568cf25b7e \
+ --hash=sha256:324721d93b998cb7367f1e6897370644751e5580ff9b370c0a50dc60a2003513 \
+ --hash=sha256:33588310b5c886dfb87dba5f013b8d27df7ffd31dc753775342a1e5ab139e59d \
+ --hash=sha256:35cf6ed4c38f054478a9df14f03c1169bb14bd98f0b1705751079b25e1cb58bc \
+ --hash=sha256:3ca482ea80626048975360c8e62be3ceb0f11803180b73163acd24bf014133a0 \
+ --hash=sha256:56ce0c106d5c3fec1038c3cca3d55ac320a5be1b44bf15116732d0bc716979a2 \
+ --hash=sha256:5a217bca51f3b91971400890905a9323ad805838ca3fa1e202a01844f485ee87 \
+ --hash=sha256:678cfa0d1e72ef41d48993a7be75a76b0725d29b820ff3cfd606a5b2b33fda01 \
+ --hash=sha256:69fd009a325cad6fbfd5b04c711a4da563c6c4854fc4c9544bff3088387c77c0 \
+ --hash=sha256:6cf9b76d6e93c62114bd19485e5cb003115c134cf9ce91f8ac924c44f8c8c3f4 \
+ --hash=sha256:74f18a4c8ca04134d2052a140322002fef535c99cdbc2a6afc18a8024d5c9d5b \
+ --hash=sha256:85f759ed59ffd1d0baad296e72780aa62ff8a71f94dc1ab340386a1207d0ea81 \
+ --hash=sha256:87086eae86a700307b544625e3ba11cc600c3c0ef8ab97b0fda0705d6db3d4e3 \
+ --hash=sha256:8814722cffcfd1fbd91edd9f3451b88a8f26a5fd41b28c1c9193949d1c689dc4 \
+ --hash=sha256:8fedec73d590fd30c4e3f0d0f4bc961aeca8390c72f3eaa1a0874d180e868ddf \
+ --hash=sha256:9515ea7f596c8092fdc9902627e51b23a75daa2c7815ed5aa8cf4f07469212ec \
+ --hash=sha256:988b738f56c665366b1e4bfd9045c3efae89ee366ca3839cd5af53eaa1401bce \
+ --hash=sha256:a2a8d873667e4fd2f34aedab02ba500b824692c6542e017075a2efc38f60a4c0 \
+ --hash=sha256:bd7cf7a8d9f34cc67220f1195884151426ce616fdc8285df9054bfa10135925f \
+ --hash=sha256:bdce70e562c69bb089523e75ef1d9625b7417c6297a76ac27b1b8b1eb51b7d0f \
+ --hash=sha256:be14b31eb3a293fc6e6aa2807c8a3224c71426f7c4e3639ccf1a2f3ffd6df8c3 \
+ --hash=sha256:be41b0c7366e5549265adf2145135dca107718fa44b6e418dc7499cfff6b4689 \
+ --hash=sha256:c310767268d88803b653fffe6d6f2f17bb9d49ffceb8d70aed50ad45ea49ab08 \
+ --hash=sha256:c58115384bdcfe9c7f644c72f10f6f42bed7cf59f7b52fe1bf7ae0a622b3a139 \
+ --hash=sha256:c640b0ef54138fde761ec99a6c7dc4ce05e80420262c20fa239e694ca371d434 \
+ --hash=sha256:ca20550bb590db16223eb9ccc5852335b48b8f597e2f6f0878bbfd9e7314eb17 \
+ --hash=sha256:d97aae66b7de41cdf5b12087b5509e4e9805ed6f562406dfcf60e8481a9a28f8 \
+ --hash=sha256:e9326ca78111e4c645f7e49cbce4ed2f3f85e17b61a563328c85a5208cf34440
# via -r requirements.in
greenlet==3.0.3 \
--hash=sha256:01bc7ea167cf943b4c802068e178bbf70ae2e8c080467070d01bfa02f337ee67 \
@@ -143,80 +152,83 @@ greenlet==3.0.3 \
--hash=sha256:fd096eb7ffef17c456cfa587523c5f92321ae02427ff955bebe9e3c63bc9f0da \
--hash=sha256:fe754d231288e1e64323cfad462fcee8f0288654c10bdf4f603a39ed923bef33
# via sqlalchemy
-psycopg2-binary==2.9.9 \
- --hash=sha256:03ef7df18daf2c4c07e2695e8cfd5ee7f748a1d54d802330985a78d2a5a6dca9 \
- --hash=sha256:0a602ea5aff39bb9fac6308e9c9d82b9a35c2bf288e184a816002c9fae930b77 \
- --hash=sha256:0c009475ee389757e6e34611d75f6e4f05f0cf5ebb76c6037508318e1a1e0d7e \
- --hash=sha256:0ef4854e82c09e84cc63084a9e4ccd6d9b154f1dbdd283efb92ecd0b5e2b8c84 \
- --hash=sha256:1236ed0952fbd919c100bc839eaa4a39ebc397ed1c08a97fc45fee2a595aa1b3 \
- --hash=sha256:143072318f793f53819048fdfe30c321890af0c3ec7cb1dfc9cc87aa88241de2 \
- --hash=sha256:15208be1c50b99203fe88d15695f22a5bed95ab3f84354c494bcb1d08557df67 \
- --hash=sha256:1873aade94b74715be2246321c8650cabf5a0d098a95bab81145ffffa4c13876 \
- --hash=sha256:18d0ef97766055fec15b5de2c06dd8e7654705ce3e5e5eed3b6651a1d2a9a152 \
- --hash=sha256:1ea665f8ce695bcc37a90ee52de7a7980be5161375d42a0b6c6abedbf0d81f0f \
- --hash=sha256:2293b001e319ab0d869d660a704942c9e2cce19745262a8aba2115ef41a0a42a \
- --hash=sha256:246b123cc54bb5361588acc54218c8c9fb73068bf227a4a531d8ed56fa3ca7d6 \
- --hash=sha256:275ff571376626195ab95a746e6a04c7df8ea34638b99fc11160de91f2fef503 \
- --hash=sha256:281309265596e388ef483250db3640e5f414168c5a67e9c665cafce9492eda2f \
- --hash=sha256:2d423c8d8a3c82d08fe8af900ad5b613ce3632a1249fd6a223941d0735fce493 \
- --hash=sha256:2e5afae772c00980525f6d6ecf7cbca55676296b580c0e6abb407f15f3706996 \
- --hash=sha256:30dcc86377618a4c8f3b72418df92e77be4254d8f89f14b8e8f57d6d43603c0f \
- --hash=sha256:31a34c508c003a4347d389a9e6fcc2307cc2150eb516462a7a17512130de109e \
- --hash=sha256:323ba25b92454adb36fa425dc5cf6f8f19f78948cbad2e7bc6cdf7b0d7982e59 \
- --hash=sha256:34eccd14566f8fe14b2b95bb13b11572f7c7d5c36da61caf414d23b91fcc5d94 \
- --hash=sha256:3a58c98a7e9c021f357348867f537017057c2ed7f77337fd914d0bedb35dace7 \
- --hash=sha256:3f78fd71c4f43a13d342be74ebbc0666fe1f555b8837eb113cb7416856c79682 \
- --hash=sha256:4154ad09dac630a0f13f37b583eae260c6aa885d67dfbccb5b02c33f31a6d420 \
- --hash=sha256:420f9bbf47a02616e8554e825208cb947969451978dceb77f95ad09c37791dae \
- --hash=sha256:4686818798f9194d03c9129a4d9a702d9e113a89cb03bffe08c6cf799e053291 \
- --hash=sha256:57fede879f08d23c85140a360c6a77709113efd1c993923c59fde17aa27599fe \
- --hash=sha256:60989127da422b74a04345096c10d416c2b41bd7bf2a380eb541059e4e999980 \
- --hash=sha256:64cf30263844fa208851ebb13b0732ce674d8ec6a0c86a4e160495d299ba3c93 \
- --hash=sha256:68fc1f1ba168724771e38bee37d940d2865cb0f562380a1fb1ffb428b75cb692 \
- --hash=sha256:6e6f98446430fdf41bd36d4faa6cb409f5140c1c2cf58ce0bbdaf16af7d3f119 \
- --hash=sha256:729177eaf0aefca0994ce4cffe96ad3c75e377c7b6f4efa59ebf003b6d398716 \
- --hash=sha256:72dffbd8b4194858d0941062a9766f8297e8868e1dd07a7b36212aaa90f49472 \
- --hash=sha256:75723c3c0fbbf34350b46a3199eb50638ab22a0228f93fb472ef4d9becc2382b \
- --hash=sha256:77853062a2c45be16fd6b8d6de2a99278ee1d985a7bd8b103e97e41c034006d2 \
- --hash=sha256:78151aa3ec21dccd5cdef6c74c3e73386dcdfaf19bced944169697d7ac7482fc \
- --hash=sha256:7f01846810177d829c7692f1f5ada8096762d9172af1b1a28d4ab5b77c923c1c \
- --hash=sha256:804d99b24ad523a1fe18cc707bf741670332f7c7412e9d49cb5eab67e886b9b5 \
- --hash=sha256:81ff62668af011f9a48787564ab7eded4e9fb17a4a6a74af5ffa6a457400d2ab \
- --hash=sha256:8359bf4791968c5a78c56103702000105501adb557f3cf772b2c207284273984 \
- --hash=sha256:83791a65b51ad6ee6cf0845634859d69a038ea9b03d7b26e703f94c7e93dbcf9 \
- --hash=sha256:8532fd6e6e2dc57bcb3bc90b079c60de896d2128c5d9d6f24a63875a95a088cf \
- --hash=sha256:876801744b0dee379e4e3c38b76fc89f88834bb15bf92ee07d94acd06ec890a0 \
- --hash=sha256:8dbf6d1bc73f1d04ec1734bae3b4fb0ee3cb2a493d35ede9badbeb901fb40f6f \
- --hash=sha256:8f8544b092a29a6ddd72f3556a9fcf249ec412e10ad28be6a0c0d948924f2212 \
- --hash=sha256:911dda9c487075abd54e644ccdf5e5c16773470a6a5d3826fda76699410066fb \
- --hash=sha256:977646e05232579d2e7b9c59e21dbe5261f403a88417f6a6512e70d3f8a046be \
- --hash=sha256:9dba73be7305b399924709b91682299794887cbbd88e38226ed9f6712eabee90 \
- --hash=sha256:a148c5d507bb9b4f2030a2025c545fccb0e1ef317393eaba42e7eabd28eb6041 \
- --hash=sha256:a6cdcc3ede532f4a4b96000b6362099591ab4a3e913d70bcbac2b56c872446f7 \
- --hash=sha256:ac05fb791acf5e1a3e39402641827780fe44d27e72567a000412c648a85ba860 \
- --hash=sha256:b0605eaed3eb239e87df0d5e3c6489daae3f7388d455d0c0b4df899519c6a38d \
- --hash=sha256:b58b4710c7f4161b5e9dcbe73bb7c62d65670a87df7bcce9e1faaad43e715245 \
- --hash=sha256:b6356793b84728d9d50ead16ab43c187673831e9d4019013f1402c41b1db9b27 \
- --hash=sha256:b76bedd166805480ab069612119ea636f5ab8f8771e640ae103e05a4aae3e417 \
- --hash=sha256:bc7bb56d04601d443f24094e9e31ae6deec9ccb23581f75343feebaf30423359 \
- --hash=sha256:c2470da5418b76232f02a2fcd2229537bb2d5a7096674ce61859c3229f2eb202 \
- --hash=sha256:c332c8d69fb64979ebf76613c66b985414927a40f8defa16cf1bc028b7b0a7b0 \
- --hash=sha256:c6af2a6d4b7ee9615cbb162b0738f6e1fd1f5c3eda7e5da17861eacf4c717ea7 \
- --hash=sha256:c77e3d1862452565875eb31bdb45ac62502feabbd53429fdc39a1cc341d681ba \
- --hash=sha256:ca08decd2697fdea0aea364b370b1249d47336aec935f87b8bbfd7da5b2ee9c1 \
- --hash=sha256:ca49a8119c6cbd77375ae303b0cfd8c11f011abbbd64601167ecca18a87e7cdd \
- --hash=sha256:cb16c65dcb648d0a43a2521f2f0a2300f40639f6f8c1ecbc662141e4e3e1ee07 \
- --hash=sha256:d2997c458c690ec2bc6b0b7ecbafd02b029b7b4283078d3b32a852a7ce3ddd98 \
- --hash=sha256:d3f82c171b4ccd83bbaf35aa05e44e690113bd4f3b7b6cc54d2219b132f3ae55 \
- --hash=sha256:dc4926288b2a3e9fd7b50dc6a1909a13bbdadfc67d93f3374d984e56f885579d \
- --hash=sha256:ead20f7913a9c1e894aebe47cccf9dc834e1618b7aa96155d2091a626e59c972 \
- --hash=sha256:ebdc36bea43063116f0486869652cb2ed7032dbc59fbcb4445c4862b5c1ecf7f \
- --hash=sha256:ed1184ab8f113e8d660ce49a56390ca181f2981066acc27cf637d5c1e10ce46e \
- --hash=sha256:ee825e70b1a209475622f7f7b776785bd68f34af6e7a46e2e42f27b659b5bc26 \
- --hash=sha256:f7ae5d65ccfbebdfa761585228eb4d0df3a8b15cfb53bd953e713e09fbb12957 \
- --hash=sha256:f7fc5a5acafb7d6ccca13bfa8c90f8c51f13d8fb87d95656d3950f0158d3ce53 \
- --hash=sha256:f9b5571d33660d5009a8b3c25dc1db560206e2d2f89d3df1cb32d72c0d117d52
- # via -r requirements.in
+psycopg==3.1.17 \
+ --hash=sha256:437e7d7925459f21de570383e2e10542aceb3b9cb972ce957fdd3826ca47edc6 \
+ --hash=sha256:96b7b13af6d5a514118b759a66b2799a8a4aa78675fa6bb0d3f7d52d67eff002
+ # via
+ # -r requirements.in
+ # psycopg
+psycopg-binary==3.1.17 \
+ --hash=sha256:00377f6963ee7e4bf71cab17c2c235ef0624df9483f3b615d86aa24cde889d42 \
+ --hash=sha256:0227885686c2cc0104ceb22d6eebc732766e9ad48710408cb0123237432e5435 \
+ --hash=sha256:02ac573f5a6e79bb6df512b3a6279f01f033bbd45c47186e8872fee45f6681d0 \
+ --hash=sha256:02cd2eb62ffc56f8c847d68765cbf461b3d11b438fe48951e44b6c563ec27d18 \
+ --hash=sha256:0340ef87a888fd940796c909e038426f4901046f61856598582a817162c64984 \
+ --hash=sha256:0b1ec6895cab887b92c303565617f994c9b9db53befda81fa2a31b76fe8a3ab1 \
+ --hash=sha256:12eab8bc91b4ba01b2ecee3b5b80501934b198f6e1f8d4b13596f3f38ba6e762 \
+ --hash=sha256:267a82548c21476120e43dc72b961f1af52c380c0b4c951bdb34cf14cb26bd35 \
+ --hash=sha256:2a05400e9314fc30bc1364865ba9f6eaa2def42b5e7e67f71f9a4430f870023e \
+ --hash=sha256:2b2a689eaede08cf91a36b10b0da6568dd6e4669200f201e082639816737992b \
+ --hash=sha256:3d0d154c780cc7b28a3a0886e8a4b18689202a1dbb522b3c771eb3a1289cf7c3 \
+ --hash=sha256:3e2cc2bbf37ff1cf11e8b871c294e3532636a3cf7f0c82518b7537158923d77b \
+ --hash=sha256:40af298b209dd77ca2f3e7eb3fbcfb87a25999fc015fcd14140bde030a164c7e \
+ --hash=sha256:420c1eb1626539c261cf3fbe099998da73eb990f9ce1a34da7feda414012ea5f \
+ --hash=sha256:4b20013051f1fd7d02b8d0766cfe8d009e8078babc00a6d39bc7e2d50a7b96af \
+ --hash=sha256:4fa26836ce074a1104249378727e1f239a01530f36bae16e77cf6c50968599b4 \
+ --hash=sha256:5ccbe8b2ec444763a51ecb1213befcbb75defc1ef36e7dd5dff501a23d7ce8cf \
+ --hash=sha256:5f5f5bcbb772d8c243d605fc7151beec760dd27532d42145a58fb74ef9c5fbf2 \
+ --hash=sha256:61104b8e7a43babf2bbaa36c08e31a12023e2f967166e99d6b052b11a4c7db06 \
+ --hash=sha256:67a5b93101bc85a95a189c0a23d02a29cf06c1080a695a0dedfdd50dd734662a \
+ --hash=sha256:6a728beefd89b430ebe2729d04ba10e05036b5e9d01648da60436000d2fcd242 \
+ --hash=sha256:6b2ae342d69684555bfe77aed5546d125b4a99012e0b83a8b3da68c8829f0935 \
+ --hash=sha256:6b40fa54a02825d3d6a8009d9a82a2b4fad80387acf2b8fd6d398fd2813cb2d9 \
+ --hash=sha256:6d4f2e15d33ed4f9776fdf23683512d76f4e7825c4b80677e9e3ce6c1b193ff2 \
+ --hash=sha256:6e3543edc18553e31a3884af3cd7eea43d6c44532d8b9b16f3e743cdf6cfe6c5 \
+ --hash=sha256:704f6393d758b12a4369887fe956b2a8c99e4aced839d9084de8e3f056015d40 \
+ --hash=sha256:73e7097b81cad9ae358334e3cec625246bb3b8013ae6bb287758dd6435e12f65 \
+ --hash=sha256:751b31c2faae0348f87f22b45ef58f704bdcfc2abdd680fa0c743c124071157e \
+ --hash=sha256:78ebb43dca7d5b41eee543cd005ee5a0256cecc74d84acf0fab4f025997b837e \
+ --hash=sha256:7b4e4c2b05f3b431e9026e82590b217e87696e7a7548f512ae8059d59fa8af3b \
+ --hash=sha256:7e28024204dc0c61094268c682041d2becfedfea2e3b46bed5f6138239304d98 \
+ --hash=sha256:83404a353240fdff5cfe9080665fdfdcaa2d4d0c5112e15b0a2fe2e59200ed57 \
+ --hash=sha256:86bb3656c8d744cc1e42003414cd6c765117d70aa23da6c0f4ff2b826e0fd0fd \
+ --hash=sha256:8c5c38129cc79d7e3ba553035b9962a442171e9f97bb1b8795c0885213f206f3 \
+ --hash=sha256:9124b6db07e8d8b11f4512b8b56cbe136bf1b7d0417d1280e62291a9dcad4408 \
+ --hash=sha256:914254849486e14aa931b0b3382cd16887f1507068ffba775cbdc5a55fe9ef19 \
+ --hash=sha256:92fad8f1aa80a5ab316c0493dc6d1b54c1dba21937e43eea7296ff4a0ccc071e \
+ --hash=sha256:93921178b9a40c60c26e47eb44970f88c49fe484aaa3bb7ec02bb8b514eab3d9 \
+ --hash=sha256:9690a535d9ccd361bbc3590bfce7fe679e847f44fa7cc97f3b885f4744ca8a2c \
+ --hash=sha256:a0c4ba73f9e7721dd6cc3e6953016652dbac206f654229b7a1a8ac182b16e689 \
+ --hash=sha256:a16abab0c1abc58feb6ab11d78d0f8178a67c3586bd70628ec7c0218ec04c4ef \
+ --hash=sha256:a343261701a8f63f0d8268f7fd32be40ffe28d24b65d905404ca03e7281f7bb5 \
+ --hash=sha256:a3f1196d76860e72d338fab0d2b6722e8d47e2285d693e366ae36011c4a5898a \
+ --hash=sha256:a880e4113af3ab84d6a0991e3f85a2424924c8a182733ab8d964421df8b5190a \
+ --hash=sha256:a89f36bf7b612ff6ed3e789bd987cbd0787cf0d66c49386fa3bad816dd7bee87 \
+ --hash=sha256:adb670031b27949c9dc5cf585c4a5a6b4469d3879fd2fb9d39b6d53e5f66b9bc \
+ --hash=sha256:b0711e46361ea3047cd049868419d030c8236a9dea7e9ed1f053cbd61a853ec9 \
+ --hash=sha256:b447ea765e71bc33a82cf070bba814b1efa77967442d116b95ccef8ce5da7631 \
+ --hash=sha256:bf424d92dd7e94705b31625b02d396297a7c8fab4b6f7de8dba6388323a7b71c \
+ --hash=sha256:c10b7713e3ed31df7319c2a72d5fea5a2536476d7695a3e1d18a1f289060997c \
+ --hash=sha256:c8a46f77ba0ca7c5a5449b777170a518fa7820e1710edb40e777c9798f00d033 \
+ --hash=sha256:ca1757a6e080086f7234dc45684e81a47a66a6dd492a37d6ce38c58a1a93e9ff \
+ --hash=sha256:d01c4faae66de60fcd3afd3720dcc8ffa03bc2087f898106da127774db12aac5 \
+ --hash=sha256:d1c0115bdf80cf6c8c9109cb10cf6f650fd1a8d841f884925e8cb12f34eb5371 \
+ --hash=sha256:d2e9ed88d9a6a475c67bf70fc8285e88ccece0391727c7701e5a512e0eafbb05 \
+ --hash=sha256:d54bcf2dfc0880bf13f38512d44b194c092794e4ee9e01d804bc6cd3eed9bfb7 \
+ --hash=sha256:d613a23f8928f30acb2b6b2398cb7775ba9852e8968e15df13807ba0d3ebd565 \
+ --hash=sha256:d90c0531e9d591bde8cea04e75107fcddcc56811b638a34853436b23c9a3cb7d \
+ --hash=sha256:dceb3930ec426623c0cacc78e447a90882981e8c49d6fea8d1e48850e24a0170 \
+ --hash=sha256:e1e867c2a729348df218a14ba1b862e627177fd57c7b4f3db0b4c708f6d03696 \
+ --hash=sha256:e6ae27b0617ad3809449964b5e901b21acff8e306abacb8ba71d5ee7c8c47eeb \
+ --hash=sha256:ea425a8dcd808a7232a5417d2633bfa543da583a2701b5228e9e29989a50deda \
+ --hash=sha256:f4028443bf25c1e04ecffdc552c0a98d826903dec76a1568dfddf5ebbbb03db7 \
+ --hash=sha256:f6898bf1ca5aa01115807643138e3e20ec603b17a811026bc4a49d43055720a7 \
+ --hash=sha256:f9ba559eabb0ba1afd4e0504fa0b10e00a212cac0c4028b8a1c3b087b5c1e5de
+ # via psycopg
+psycopg-pool==3.2.1 \
+ --hash=sha256:060b551d1b97a8d358c668be58b637780b884de14d861f4f5ecc48b7563aafb7 \
+ --hash=sha256:6509a75c073590952915eddbba7ce8b8332a440a31e77bba69561483492829ad
+ # via psycopg
pycparser==2.21 \
--hash=sha256:8ee45429555515e1f6b185e78100aea234072576aa43ab53aefcae078162fca9 \
--hash=sha256:e644fdec12f7872f86c58ff790da456218b10f863970249516d60a5eaca77206
@@ -279,4 +291,7 @@ sqlalchemy==2.0.25 \
typing-extensions==4.9.0 \
--hash=sha256:23478f88c37f27d76ac8aee6c905017a143b0b1b886c3c9f66bc2fd94f9f5783 \
--hash=sha256:af72aea155e91adfc61c3ae9e0e342dbc0cba726d6cba4b6c72c1f34e47291cd
- # via sqlalchemy
+ # via
+ # psycopg
+ # psycopg-pool
+ # sqlalchemy
diff --git a/tests/core/db/test.sh b/tests/core/db/test.sh
index 6ad823626..f18fe27fb 100755
--- a/tests/core/db/test.sh
+++ b/tests/core/db/test.sh
@@ -312,7 +312,7 @@ do
elif [ "$test" = "postgres" ] ; then
echo "💾 Running tests with PostgreSQL database ..."
echo "ℹ️ Keeping the MULTISITE variable to yes and multisite settings ..."
- find . -type f -name 'docker-compose.*' -exec sed -i 's@DATABASE_URI: ".*"$@DATABASE_URI: "postgresql://bunkerweb:secret\@bw-db:5432/db"@' {} \;
+ find . -type f -name 'docker-compose.*' -exec sed -i 's@DATABASE_URI: ".*"$@DATABASE_URI: "postgresql+psycopg://bunkerweb:secret\@bw-db:5432/db"@' {} \;
echo "💾 Starting postgres ..."
docker compose -f docker-compose.postgres.yml up -d
diff --git a/tests/core/dnsbl/Dockerfile b/tests/core/dnsbl/Dockerfile
index fe3cea3e7..29c73e1f0 100644
--- a/tests/core/dnsbl/Dockerfile
+++ b/tests/core/dnsbl/Dockerfile
@@ -1,4 +1,4 @@
-FROM python:3.12.1-alpine3.18@sha256:af0d8da43677e3000ebdf4045508d891a87e7bd2d3ec87bc6e40403be97291b8
+FROM python:3.12.1-alpine3.18@sha256:fb759579d60cfe1f70b110a27be95aaa7cf758d2fa21cf54fffb71c2ba3f8034
WORKDIR /tmp
diff --git a/tests/core/dnsbl/init/Dockerfile b/tests/core/dnsbl/init/Dockerfile
index e5e0eeed5..8392c38b5 100644
--- a/tests/core/dnsbl/init/Dockerfile
+++ b/tests/core/dnsbl/init/Dockerfile
@@ -1,4 +1,4 @@
-FROM python:3.12.1-alpine3.18@sha256:af0d8da43677e3000ebdf4045508d891a87e7bd2d3ec87bc6e40403be97291b8
+FROM python:3.12.1-alpine3.18@sha256:fb759579d60cfe1f70b110a27be95aaa7cf758d2fa21cf54fffb71c2ba3f8034
# Install firefox and geckodriver
RUN apk add --no-cache --virtual .build-deps curl grep zip wget && \
diff --git a/tests/core/dnsbl/init/requirements.in b/tests/core/dnsbl/init/requirements.in
index 95f2ad4f2..4f5f6e55f 100644
--- a/tests/core/dnsbl/init/requirements.in
+++ b/tests/core/dnsbl/init/requirements.in
@@ -1 +1 @@
-selenium==4.16.0
+selenium<4.17.0
diff --git a/tests/core/errors/Dockerfile b/tests/core/errors/Dockerfile
index e5e0eeed5..8392c38b5 100644
--- a/tests/core/errors/Dockerfile
+++ b/tests/core/errors/Dockerfile
@@ -1,4 +1,4 @@
-FROM python:3.12.1-alpine3.18@sha256:af0d8da43677e3000ebdf4045508d891a87e7bd2d3ec87bc6e40403be97291b8
+FROM python:3.12.1-alpine3.18@sha256:fb759579d60cfe1f70b110a27be95aaa7cf758d2fa21cf54fffb71c2ba3f8034
# Install firefox and geckodriver
RUN apk add --no-cache --virtual .build-deps curl grep zip wget && \
diff --git a/tests/core/errors/requirements.in b/tests/core/errors/requirements.in
index 49cb1341f..45ceb3f45 100644
--- a/tests/core/errors/requirements.in
+++ b/tests/core/errors/requirements.in
@@ -1,2 +1,2 @@
requests==2.31.0
-selenium==4.16.0
+selenium<4.17.0
diff --git a/tests/core/greylist/Dockerfile b/tests/core/greylist/Dockerfile
index fe3cea3e7..29c73e1f0 100644
--- a/tests/core/greylist/Dockerfile
+++ b/tests/core/greylist/Dockerfile
@@ -1,4 +1,4 @@
-FROM python:3.12.1-alpine3.18@sha256:af0d8da43677e3000ebdf4045508d891a87e7bd2d3ec87bc6e40403be97291b8
+FROM python:3.12.1-alpine3.18@sha256:fb759579d60cfe1f70b110a27be95aaa7cf758d2fa21cf54fffb71c2ba3f8034
WORKDIR /tmp
diff --git a/tests/core/greylist/api/Dockerfile b/tests/core/greylist/api/Dockerfile
index aba06a1e0..00c640d42 100644
--- a/tests/core/greylist/api/Dockerfile
+++ b/tests/core/greylist/api/Dockerfile
@@ -1,4 +1,4 @@
-FROM python:3.12.1-alpine3.18@sha256:af0d8da43677e3000ebdf4045508d891a87e7bd2d3ec87bc6e40403be97291b8
+FROM python:3.12.1-alpine3.18@sha256:fb759579d60cfe1f70b110a27be95aaa7cf758d2fa21cf54fffb71c2ba3f8034
WORKDIR /tmp
diff --git a/tests/core/greylist/api/requirements.in b/tests/core/greylist/api/requirements.in
index c70d8e9ca..01e8a7398 100644
--- a/tests/core/greylist/api/requirements.in
+++ b/tests/core/greylist/api/requirements.in
@@ -1,2 +1,2 @@
fastapi==0.109.0
-uvicorn[standard]==0.25.0
+uvicorn[standard]==0.27.0
diff --git a/tests/core/greylist/api/requirements.txt b/tests/core/greylist/api/requirements.txt
index 9f6ef8206..f64cba8e6 100644
--- a/tests/core/greylist/api/requirements.txt
+++ b/tests/core/greylist/api/requirements.txt
@@ -183,9 +183,9 @@ pydantic-core==2.14.6 \
--hash=sha256:fd9e98b408384989ea4ab60206b8e100d8687da18b5c813c11e92fd8212a98e0 \
--hash=sha256:ffff855100bc066ff2cd3aa4a60bc9534661816b110f0243e59503ec2df38421
# via pydantic
-python-dotenv==1.0.0 \
- --hash=sha256:a8df96034aae6d2d50a4ebe8216326c61c3eb64836776504fcca410e5937a3ba \
- --hash=sha256:f5971a9226b701070a4bf2c38c89e5a3f0d64de8debda981d1db98583009122a
+python-dotenv==1.0.1 \
+ --hash=sha256:e324ee90a023d808f1959c46bcbc04446a10ced277783dc6ee09987c37ec10ca \
+ --hash=sha256:f7b63ef50f1b690dddf550d03497b66d609393b40b564ed0d674909a68ebf16a
# via uvicorn
pyyaml==6.0.1 \
--hash=sha256:04ac92ad1925b2cff1db0cfebffb6ffc43457495c9b3c39d3fcae417d7125dc5 \
@@ -217,6 +217,7 @@ pyyaml==6.0.1 \
--hash=sha256:8d4e9c88387b0f5c7d5f281e55304de64cf7f9c0021a3525bd3b1c542da3b0e4 \
--hash=sha256:9046c58c4395dff28dd494285c82ba00b546adfc7ef001486fbf0324bc174fba \
--hash=sha256:9eb6caa9a297fc2c2fb8862bc5370d0303ddba53ba97e71f08023b6cd73d16a8 \
+ --hash=sha256:a08c6f0fe150303c1c6b71ebcd7213c2858041a7e01975da3a99aed1e7a378ef \
--hash=sha256:a0cd17c15d3bb3fa06978b4e8958dcdc6e0174ccea823003a106c7d4d7899ac5 \
--hash=sha256:afd7e57eddb1a54f0f1a974bc4391af8bcce0b444685d936840f125cf046d5bd \
--hash=sha256:b1275ad35a5d18c62a7220633c913e1b42d44b46ee12554e5fd39c70a243d6a3 \
@@ -257,9 +258,9 @@ typing-extensions==4.9.0 \
# pydantic-core
# starlette
# uvicorn
-uvicorn==0.25.0 \
- --hash=sha256:6dddbad1d7ee0f5140aba5ec138ddc9612c5109399903828b4874c9937f009c2 \
- --hash=sha256:ce107f5d9bd02b4636001a77a4e74aab5e1e2b146868ebbad565237145af444c
+uvicorn==0.27.0 \
+ --hash=sha256:890b00f6c537d58695d3bb1f28e23db9d9e7a17cbcc76d7457c499935f933e24 \
+ --hash=sha256:c855578045d45625fd027367f7653d249f7c49f9361ba15cf9624186b26b8eb6
# via
# -r requirements.in
# uvicorn
diff --git a/tests/core/greylist/init/Dockerfile b/tests/core/greylist/init/Dockerfile
index 337a70388..3048b84c5 100644
--- a/tests/core/greylist/init/Dockerfile
+++ b/tests/core/greylist/init/Dockerfile
@@ -1,4 +1,4 @@
-FROM python:3.12.1-alpine3.18@sha256:af0d8da43677e3000ebdf4045508d891a87e7bd2d3ec87bc6e40403be97291b8
+FROM python:3.12.1-alpine3.18@sha256:fb759579d60cfe1f70b110a27be95aaa7cf758d2fa21cf54fffb71c2ba3f8034
WORKDIR /tmp
diff --git a/tests/core/gzip/Dockerfile b/tests/core/gzip/Dockerfile
index fe3cea3e7..29c73e1f0 100644
--- a/tests/core/gzip/Dockerfile
+++ b/tests/core/gzip/Dockerfile
@@ -1,4 +1,4 @@
-FROM python:3.12.1-alpine3.18@sha256:af0d8da43677e3000ebdf4045508d891a87e7bd2d3ec87bc6e40403be97291b8
+FROM python:3.12.1-alpine3.18@sha256:fb759579d60cfe1f70b110a27be95aaa7cf758d2fa21cf54fffb71c2ba3f8034
WORKDIR /tmp
diff --git a/tests/core/headers/Dockerfile b/tests/core/headers/Dockerfile
index fe3cea3e7..29c73e1f0 100644
--- a/tests/core/headers/Dockerfile
+++ b/tests/core/headers/Dockerfile
@@ -1,4 +1,4 @@
-FROM python:3.12.1-alpine3.18@sha256:af0d8da43677e3000ebdf4045508d891a87e7bd2d3ec87bc6e40403be97291b8
+FROM python:3.12.1-alpine3.18@sha256:fb759579d60cfe1f70b110a27be95aaa7cf758d2fa21cf54fffb71c2ba3f8034
WORKDIR /tmp
diff --git a/tests/core/inject/Dockerfile b/tests/core/inject/Dockerfile
index fe3cea3e7..29c73e1f0 100644
--- a/tests/core/inject/Dockerfile
+++ b/tests/core/inject/Dockerfile
@@ -1,4 +1,4 @@
-FROM python:3.12.1-alpine3.18@sha256:af0d8da43677e3000ebdf4045508d891a87e7bd2d3ec87bc6e40403be97291b8
+FROM python:3.12.1-alpine3.18@sha256:fb759579d60cfe1f70b110a27be95aaa7cf758d2fa21cf54fffb71c2ba3f8034
WORKDIR /tmp
diff --git a/tests/core/limit/Dockerfile b/tests/core/limit/Dockerfile
index fe3cea3e7..29c73e1f0 100644
--- a/tests/core/limit/Dockerfile
+++ b/tests/core/limit/Dockerfile
@@ -1,4 +1,4 @@
-FROM python:3.12.1-alpine3.18@sha256:af0d8da43677e3000ebdf4045508d891a87e7bd2d3ec87bc6e40403be97291b8
+FROM python:3.12.1-alpine3.18@sha256:fb759579d60cfe1f70b110a27be95aaa7cf758d2fa21cf54fffb71c2ba3f8034
WORKDIR /tmp
diff --git a/tests/core/misc/Dockerfile b/tests/core/misc/Dockerfile
index 825bc5f32..b4546fa57 100644
--- a/tests/core/misc/Dockerfile
+++ b/tests/core/misc/Dockerfile
@@ -1,4 +1,4 @@
-FROM python:3.12.1-alpine3.18@sha256:af0d8da43677e3000ebdf4045508d891a87e7bd2d3ec87bc6e40403be97291b8
+FROM python:3.12.1-alpine3.18@sha256:fb759579d60cfe1f70b110a27be95aaa7cf758d2fa21cf54fffb71c2ba3f8034
WORKDIR /tmp
diff --git a/tests/core/modsecurity/Dockerfile b/tests/core/modsecurity/Dockerfile
index fe3cea3e7..29c73e1f0 100644
--- a/tests/core/modsecurity/Dockerfile
+++ b/tests/core/modsecurity/Dockerfile
@@ -1,4 +1,4 @@
-FROM python:3.12.1-alpine3.18@sha256:af0d8da43677e3000ebdf4045508d891a87e7bd2d3ec87bc6e40403be97291b8
+FROM python:3.12.1-alpine3.18@sha256:fb759579d60cfe1f70b110a27be95aaa7cf758d2fa21cf54fffb71c2ba3f8034
WORKDIR /tmp
diff --git a/tests/core/redirect/Dockerfile b/tests/core/redirect/Dockerfile
index e5e0eeed5..8392c38b5 100644
--- a/tests/core/redirect/Dockerfile
+++ b/tests/core/redirect/Dockerfile
@@ -1,4 +1,4 @@
-FROM python:3.12.1-alpine3.18@sha256:af0d8da43677e3000ebdf4045508d891a87e7bd2d3ec87bc6e40403be97291b8
+FROM python:3.12.1-alpine3.18@sha256:fb759579d60cfe1f70b110a27be95aaa7cf758d2fa21cf54fffb71c2ba3f8034
# Install firefox and geckodriver
RUN apk add --no-cache --virtual .build-deps curl grep zip wget && \
diff --git a/tests/core/redirect/requirements.in b/tests/core/redirect/requirements.in
index 49cb1341f..45ceb3f45 100644
--- a/tests/core/redirect/requirements.in
+++ b/tests/core/redirect/requirements.in
@@ -1,2 +1,2 @@
requests==2.31.0
-selenium==4.16.0
+selenium<4.17.0
diff --git a/tests/core/redis/Dockerfile b/tests/core/redis/Dockerfile
index 847ea4e7c..4d953571f 100644
--- a/tests/core/redis/Dockerfile
+++ b/tests/core/redis/Dockerfile
@@ -1,4 +1,4 @@
-FROM python:3.12.1-alpine3.18@sha256:af0d8da43677e3000ebdf4045508d891a87e7bd2d3ec87bc6e40403be97291b8
+FROM python:3.12.1-alpine3.18@sha256:fb759579d60cfe1f70b110a27be95aaa7cf758d2fa21cf54fffb71c2ba3f8034
# Install firefox and geckodriver
RUN apk add --no-cache --virtual .build-deps curl grep zip wget && \
diff --git a/tests/core/redis/Dockerfile.redis b/tests/core/redis/Dockerfile.redis
deleted file mode 100644
index 5ee0740ad..000000000
--- a/tests/core/redis/Dockerfile.redis
+++ /dev/null
@@ -1,9 +0,0 @@
-FROM redis:7-alpine@sha256:2d148c557c85309c7cf1bbf15ebc21d5fc370ab1cb913a6c19b74bd29d10801c
-
-RUN apk add --no-cache bash openssl
-
-COPY entrypoint.sh .
-
-RUN chmod +x entrypoint.sh
-
-ENTRYPOINT [ "./entrypoint.sh" ]
diff --git a/tests/core/redis/docker-compose.test.yml b/tests/core/redis/docker-compose.test.yml
index ab2539d7e..9c62463ce 100644
--- a/tests/core/redis/docker-compose.test.yml
+++ b/tests/core/redis/docker-compose.test.yml
@@ -12,11 +12,17 @@ services:
REDIS_PORT: "6379"
REDIS_DATABASE: "0"
REDIS_SSL: "no"
+ REDIS_USERNAME: ""
+ REDIS_PASSWORD: ""
+ REDIS_SENTINEL_HOSTS: ""
+ REDIS_SENTINEL_USERNAME: ""
+ REDIS_SENTINEL_PASSWORD: ""
+ REDIS_SENTINEL_MASTER: "bw-master"
extra_hosts:
- - "www.example.com:1.0.0.2"
+ - "www.example.com:1.0.0.254"
networks:
bw-services:
- ipv4_address: 1.0.0.3
+ ipv4_address: 1.0.0.253
networks:
bw-services:
diff --git a/tests/core/redis/docker-compose.yml b/tests/core/redis/docker-compose.yml
index 4b2c73559..b31dc135d 100644
--- a/tests/core/redis/docker-compose.yml
+++ b/tests/core/redis/docker-compose.yml
@@ -30,6 +30,12 @@ services:
REDIS_PORT: "6379"
REDIS_DATABASE: "0"
REDIS_SSL: "no"
+ REDIS_USERNAME: ""
+ REDIS_PASSWORD: ""
+ REDIS_SENTINEL_HOSTS: ""
+ REDIS_SENTINEL_USERNAME: ""
+ REDIS_SENTINEL_PASSWORD: ""
+ REDIS_SENTINEL_MASTER: "bw-master"
CUSTOM_CONF_SERVER_HTTP_ready: |
location /ready {
default_type 'text/plain';
@@ -42,7 +48,7 @@ services:
networks:
bw-universe:
bw-services:
- ipv4_address: 1.0.0.2
+ ipv4_address: 1.0.0.254
bw-scheduler:
image: bunkerity/bunkerweb-scheduler:1.5.5
@@ -67,15 +73,78 @@ services:
- bw-docker
bw-redis:
- build:
- context: .
- dockerfile: Dockerfile.redis
+ image: bitnami/redis:7.2
+ volumes:
+ - ./acl:/acl
+ - ./tls:/tls
environment:
- REDIS_PORT: "6379"
- REDIS_SSL: "no"
+ REDIS_PORT_NUMBER: "6379"
+ REDIS_TLS_PORT_NUMBER: "6379"
+ REDIS_ACLFILE: "/acl/redis.acl"
+ REDIS_TLS_ENABLED: "no"
+ REDIS_TLS_CERT_FILE: "/tls/redis.pem"
+ REDIS_TLS_KEY_FILE: "/tls/redis.key"
+ REDIS_TLS_CA_FILE: "/tls/ca.crt"
+ REDIS_TLS_AUTH_CLIENTS: "yes"
+ REDIS_REPLICATION_MODE: "master"
+ REDIS_MASTER_SET: "bw-master"
+ ALLOW_EMPTY_PASSWORD: "yes"
networks:
- bw-services:
- ipv4_address: 1.0.0.4
+ - bw-services
+
+ bw-redis-slave:
+ image: bitnami/redis:7.2
+ volumes:
+ - ./acl:/acl
+ - ./tls:/tls
+ environment:
+ REDIS_PORT_NUMBER: "6379"
+ REDIS_TLS_PORT_NUMBER: "6379"
+ REDIS_ACLFILE: "/acl/redis.acl"
+ REDIS_TLS_ENABLED: "no"
+ REDIS_TLS_CERT_FILE: "/tls/redis.pem"
+ REDIS_TLS_KEY_FILE: "/tls/redis.key"
+ REDIS_TLS_CA_FILE: "/tls/ca.crt"
+ REDIS_TLS_AUTH_CLIENTS: "yes"
+ REDIS_REPLICATION_MODE: "slave"
+ REDIS_MASTER_HOST: "bw-redis"
+ REDIS_MASTER_SET: "bw-master"
+ REDIS_MASTER_PORT_NUMBER: "6379"
+ REDIS_MASTER_PASSWORD: ""
+ ALLOW_EMPTY_PASSWORD: "yes"
+ depends_on:
+ - bw-redis
+ networks:
+ - bw-services
+ deploy:
+ replicas: 2
+
+ bw-redis-sentinel:
+ image: bitnami/redis-sentinel:7.2
+ command: /opt/bitnami/scripts/redis-sentinel/run.sh --aclfile /acl/sentinel.acl
+ volumes:
+ - ./acl:/acl
+ - ./tls:/tls
+ environment:
+ REDIS_SENTINEL_PORT_NUMBER: "26379"
+ REDIS_SENTINEL_TLS_PORT_NUMBER: "0"
+ REDIS_SENTINEL_TLS_ENABLED: "no"
+ REDIS_SENTINEL_TLS_CERT_FILE: "/tls/sentinel.pem"
+ REDIS_SENTINEL_TLS_KEY_FILE: "/tls/sentinel.key"
+ REDIS_SENTINEL_TLS_CA_FILE: "/tls/sentinel_ca.crt"
+ REDIS_SENTINEL_TLS_AUTH_CLIENTS: "no"
+ REDIS_MASTER_HOST: "bw-redis"
+ REDIS_MASTER_SET: "bw-master"
+ REDIS_MASTER_PORT_NUMBER: "6379"
+ REDIS_MASTER_PASSWORD: ""
+ ALLOW_EMPTY_PASSWORD: "yes"
+ depends_on:
+ - bw-redis
+ - bw-redis-slave
+ networks:
+ - bw-services
+ deploy:
+ replicas: 3
networks:
bw-universe:
diff --git a/tests/core/redis/entrypoint.sh b/tests/core/redis/entrypoint.sh
deleted file mode 100644
index dadd79f62..000000000
--- a/tests/core/redis/entrypoint.sh
+++ /dev/null
@@ -1,31 +0,0 @@
-#!/bin/bash
-set -e
-
-command="redis-server"
-
-if [ "$REDIS_SSL" = "yes" ]; then
- mkdir /tls
-
- openssl genrsa -out /tls/ca.key 4096
- openssl req \
- -x509 -new -nodes -sha256 \
- -key /tls/ca.key \
- -days 365 \
- -subj /CN=bw-redis/ \
- -out /tls/ca.crt
-
- openssl req \
- -x509 -nodes -newkey rsa:4096 \
- -keyout /tls/redis.key \
- -out /tls/redis.pem \
- -days 365 \
- -subj /CN=bw-redis/
-
- chmod -R 640 /tls
-
- command+=" --tls-port ${REDIS_PORT:-6379} --port 0 --tls-cert-file /tls/redis.pem --tls-key-file /tls/redis.key --tls-ca-cert-file /tls/ca.crt --tls-auth-clients no"
-else
- command+=" --port ${REDIS_PORT:-6379}"
-fi
-
-$command
diff --git a/tests/core/redis/main.py b/tests/core/redis/main.py
index de7a0ff38..82a87470b 100644
--- a/tests/core/redis/main.py
+++ b/tests/core/redis/main.py
@@ -1,7 +1,7 @@
from fastapi import FastAPI
from multiprocessing import Process
from os import getenv
-from redis import Redis
+from redis import Redis, Sentinel
from requests import get
from selenium import webdriver
from selenium.webdriver.firefox.options import Options
@@ -14,7 +14,7 @@ from uvicorn import run
fastapi_proc = None
-ip_to_check = "1.0.0.3" if getenv("TEST_TYPE", "docker") == "docker" else "127.0.0.1"
+ip_to_check = "1.0.0.253" if getenv("TEST_TYPE", "docker") == "docker" else "127.0.0.1"
try:
ready = False
@@ -62,20 +62,50 @@ try:
redis_db = int(redis_db)
redis_ssl = getenv("REDIS_SSL", "no") == "yes"
+ sentinel_hosts = getenv("REDIS_SENTINEL_HOSTS", [])
- print(
- f"ℹ️ Trying to connect to Redis with the following parameters:\nhost: {redis_host}\nport: {redis_port}\ndb: {redis_db}\nssl: {redis_ssl}",
- flush=True,
- )
+ if isinstance(sentinel_hosts, str):
+ sentinel_hosts = [host.split(":") if ":" in host else host for host in sentinel_hosts.split(" ") if host]
- redis_client = Redis(
- host=redis_host,
- port=redis_port,
- db=redis_db,
- ssl=redis_ssl,
- socket_timeout=1,
- ssl_cert_reqs=None,
- )
+ if sentinel_hosts:
+ sentinel_username = getenv("REDIS_SENTINEL_USERNAME", None) or None
+ sentinel_password = getenv("REDIS_SENTINEL_PASSWORD", None) or None
+ sentinel_master = getenv("REDIS_SENTINEL_MASTER", "bw-master")
+
+ print(
+ f"ℹ️ Trying to connect to Redis Sentinel with the following parameters:\nhosts: {sentinel_hosts}\nmaster: {sentinel_master}\nssl: {redis_ssl}\nusername: {sentinel_username}\npassword: {sentinel_password}",
+ flush=True,
+ )
+ sentinel = Sentinel(sentinel_hosts, username=sentinel_username, password=sentinel_password, sentinel_kwargs=dict(ssl=redis_ssl), socket_timeout=1) # type: ignore
+
+ print(
+ f"ℹ️ Trying to get a Redis Sentinel slave for master {sentinel_master} with the following parameters:\n"
+ + f"host: {redis_host}\nport: {redis_port}\ndb: {redis_db}\nssl: {redis_ssl}\nusername: {getenv('REDIS_USERNAME', None) or None}\npassword: {getenv('REDIS_PASSWORD', None) or None}",
+ flush=True,
+ )
+ redis_client = sentinel.slave_for(
+ sentinel_master,
+ db=redis_db,
+ username=getenv("REDIS_USERNAME", None) or None,
+ password=getenv("REDIS_PASSWORD", None) or None,
+ )
+ else:
+ print(
+ "ℹ️ Trying to connect to Redis with the following parameters:\n"
+ + f"host: {redis_host}\nport: {redis_port}\ndb: {redis_db}\nssl: {redis_ssl}\nusername: {getenv('REDIS_USERNAME', None) or None}\npassword: {getenv('REDIS_PASSWORD', None) or None}",
+ flush=True,
+ )
+
+ redis_client = Redis(
+ host=redis_host,
+ port=redis_port,
+ db=redis_db,
+ username=getenv("REDIS_USERNAME", None) or None,
+ password=getenv("REDIS_PASSWORD", None) or None,
+ ssl=redis_ssl,
+ socket_timeout=1,
+ ssl_cert_reqs="none",
+ )
if not redis_client.ping():
print("❌ Redis is not reachable, exiting ...", flush=True)
@@ -84,7 +114,7 @@ try:
use_reverse_scan = getenv("USE_REVERSE_SCAN", "no") == "yes"
if use_reverse_scan:
- if ip_to_check == "1.0.0.3":
+ if ip_to_check == "1.0.0.253":
print("ℹ️ Testing Reverse Scan, starting FastAPI ...", flush=True)
app = FastAPI()
fastapi_proc = Process(target=run, args=(app,), kwargs=dict(host="0.0.0.0", port=8080))
@@ -112,7 +142,7 @@ try:
print("ℹ️ The request was blocked, checking Redis ...", flush=True)
- port_to_check = "8080" if ip_to_check == "1.0.0.3" else "80"
+ port_to_check = "8080" if ip_to_check == "1.0.0.253" else "80"
key_value = redis_client.get(f"plugin_reverse_scan_{ip_to_check}:{port_to_check}")
@@ -368,7 +398,7 @@ try:
# flush=True,
# )
- # if ip_to_check == "1.0.0.3":
+ # if ip_to_check == "1.0.0.253":
# print(
# "ℹ️ Checking if the dnsbl keys were created ...",
# flush=True,
diff --git a/tests/core/redis/requirements.in b/tests/core/redis/requirements.in
index e1fced6d7..7353799e7 100644
--- a/tests/core/redis/requirements.in
+++ b/tests/core/redis/requirements.in
@@ -1,5 +1,5 @@
fastapi==0.109.0
redis==5.0.1
requests==2.31.0
-selenium==4.16.0
-uvicorn[standard]==0.25.0
+selenium<4.17.0
+uvicorn[standard]==0.27.0
diff --git a/tests/core/redis/requirements.txt b/tests/core/redis/requirements.txt
index 278878e84..62e26f2b2 100644
--- a/tests/core/redis/requirements.txt
+++ b/tests/core/redis/requirements.txt
@@ -308,9 +308,9 @@ pysocks==1.7.1 \
--hash=sha256:2725bd0a9925919b9b51739eea5f9e2bae91e83288108a9ad338b2e3a4435ee5 \
--hash=sha256:3f8804571ebe159c380ac6de37643bb4685970655d3bba243530d6558b799aa0
# via urllib3
-python-dotenv==1.0.0 \
- --hash=sha256:a8df96034aae6d2d50a4ebe8216326c61c3eb64836776504fcca410e5937a3ba \
- --hash=sha256:f5971a9226b701070a4bf2c38c89e5a3f0d64de8debda981d1db98583009122a
+python-dotenv==1.0.1 \
+ --hash=sha256:e324ee90a023d808f1959c46bcbc04446a10ced277783dc6ee09987c37ec10ca \
+ --hash=sha256:f7b63ef50f1b690dddf550d03497b66d609393b40b564ed0d674909a68ebf16a
# via uvicorn
pyyaml==6.0.1 \
--hash=sha256:04ac92ad1925b2cff1db0cfebffb6ffc43457495c9b3c39d3fcae417d7125dc5 \
@@ -342,6 +342,7 @@ pyyaml==6.0.1 \
--hash=sha256:8d4e9c88387b0f5c7d5f281e55304de64cf7f9c0021a3525bd3b1c542da3b0e4 \
--hash=sha256:9046c58c4395dff28dd494285c82ba00b546adfc7ef001486fbf0324bc174fba \
--hash=sha256:9eb6caa9a297fc2c2fb8862bc5370d0303ddba53ba97e71f08023b6cd73d16a8 \
+ --hash=sha256:a08c6f0fe150303c1c6b71ebcd7213c2858041a7e01975da3a99aed1e7a378ef \
--hash=sha256:a0cd17c15d3bb3fa06978b4e8958dcdc6e0174ccea823003a106c7d4d7899ac5 \
--hash=sha256:afd7e57eddb1a54f0f1a974bc4391af8bcce0b444685d936840f125cf046d5bd \
--hash=sha256:b1275ad35a5d18c62a7220633c913e1b42d44b46ee12554e5fd39c70a243d6a3 \
@@ -416,9 +417,9 @@ urllib3==2.1.0 \
# via
# requests
# selenium
-uvicorn==0.25.0 \
- --hash=sha256:6dddbad1d7ee0f5140aba5ec138ddc9612c5109399903828b4874c9937f009c2 \
- --hash=sha256:ce107f5d9bd02b4636001a77a4e74aab5e1e2b146868ebbad565237145af444c
+uvicorn==0.27.0 \
+ --hash=sha256:890b00f6c537d58695d3bb1f28e23db9d9e7a17cbcc76d7457c499935f933e24 \
+ --hash=sha256:c855578045d45625fd027367f7653d249f7c49f9361ba15cf9624186b26b8eb6
# via
# -r requirements.in
# uvicorn
diff --git a/tests/core/redis/test.sh b/tests/core/redis/test.sh
index 4d3695f72..c42c23815 100755
--- a/tests/core/redis/test.sh
+++ b/tests/core/redis/test.sh
@@ -12,8 +12,55 @@ fi
echo "🧰 Building redis stack for integration \"$integration\" ..."
+echo "🧰 Generating redis certs ..."
+sudo rm -rf tls
+mkdir tls
+openssl genrsa -out tls/ca.key 4096
+openssl req \
+ -x509 -new -nodes -sha256 \
+ -key tls/ca.key \
+ -days 365 \
+ -subj /CN=bw-redis/ \
+ -out tls/ca.crt
+
+openssl req \
+ -x509 -nodes -newkey rsa:4096 \
+ -keyout tls/redis.key \
+ -out tls/redis.pem \
+ -days 365 \
+ -subj /CN=bw-redis/
+
+openssl genrsa -out tls/sentinel_ca.key 4096
+openssl req \
+ -x509 -new -nodes -sha256 \
+ -key tls/sentinel_ca.key \
+ -days 365 \
+ -subj /CN=bw-redis-sentinel/ \
+ -out tls/sentinel_ca.crt
+
+openssl req \
+ -x509 -nodes -newkey rsa:4096 \
+ -keyout tls/sentinel.key \
+ -out tls/sentinel.pem \
+ -days 365 \
+ -subj /CN=bw-redis-sentinel/
+
+sudo chmod -R 777 tls
+echo "🧰 Certs generated ✅"
+
+echo "🧰 Generating redis acl files ..."
+sudo rm -rf acl
+mkdir acl
+
# Starting stack
if [ "$integration" == "docker" ] ; then
+ echo "user default on nopass +@all ~* &* +@all -@all +@all" > acl/redis.acl
+ echo "user bunkerweb on >secret +@all ~* +@all -@all +@all" >> acl/redis.acl
+ echo "user default on nopass +@all ~* &* +@all -@all +@all" > acl/sentinel.acl
+ echo "user bunkerweb_sentinel on >sentinel_secret +@all ~* +@all -@all +@all" >> acl/sentinel.acl
+ sudo chmod -R 777 acl
+ echo "🧰 Redis acl files generated ✅"
+
docker compose pull bw-docker
# shellcheck disable=SC2181
if [ $? -ne 0 ] ; then
@@ -37,6 +84,11 @@ if [ "$integration" == "docker" ] ; then
exit 1
fi
else
+ echo "user default on nopass +@all ~* +@all -@all +@all" > acl/redis.acl
+ echo "user bunkerweb on >secret +@all ~* +@all -@all +@all" >> acl/redis.acl
+ sudo chmod -R 777 acl
+ echo "🧰 Redis acl files generated ✅"
+
sudo systemctl stop bunkerweb
sudo sed -i "/^USE_BLACKLIST=/d" /etc/bunkerweb/variables.env
echo "BLACKLIST_IP_URLS=" | sudo tee -a /etc/bunkerweb/variables.env
@@ -58,24 +110,6 @@ else
fi
echo "🧰 Redis installed ✅"
- echo "🧰 Generating redis certs ..."
- mkdir tls
- openssl genrsa -out tls/ca.key 4096
- openssl req \
- -x509 -new -nodes -sha256 \
- -key tls/ca.key \
- -days 365 \
- -subj /CN=bw-redis/ \
- -out tls/ca.crt
- openssl req \
- -x509 -nodes -newkey rsa:4096 \
- -keyout tls/redis.key \
- -out tls/redis.pem \
- -days 365 \
- -subj /CN=bw-redis/
- sudo chmod -R 777 tls
- echo "🧰 Certs generated ✅"
-
echo "USE_REDIS=yes" | sudo tee -a /etc/bunkerweb/variables.env
echo "REDIS_HOST=127.0.0.1" | sudo tee -a /etc/bunkerweb/variables.env
echo "REDIS_PORT=6379" | sudo tee -a /etc/bunkerweb/variables.env
@@ -95,10 +129,21 @@ cleanup_stack () {
find . -type f -name 'docker-compose.*' -exec sed -i 's@USE_REVERSE_SCAN: "yes"@USE_REVERSE_SCAN: "no"@' {} \;
find . -type f -name 'docker-compose.*' -exec sed -i 's@USE_ANTIBOT: "cookie"@USE_ANTIBOT: "no"@' {} \;
find . -type f -name 'docker-compose.*' -exec sed -i 's@REDIS_PORT: "[0-9]*"@REDIS_PORT: "6379"@' {} \;
+ find . -type f -name 'docker-compose.*' -exec sed -i 's@REDIS_PORT_NUMBER: "[0-9]*"@REDIS_PORT_NUMBER: "6379"@' {} \;
+ find . -type f -name 'docker-compose.*' -exec sed -i 's@REDIS_MASTER_PORT_NUMBER: "[0-9]*"@REDIS_MASTER_PORT_NUMBER: "6379"@' {} \;
+ find . -type f -name 'docker-compose.*' -exec sed -i 's@REDIS_SENTINEL_PORT_NUMBER: "[0-9]*"@REDIS_SENTINEL_PORT_NUMBER: "26379"@' {} \;
find . -type f -name 'docker-compose.*' -exec sed -i 's@REDIS_DATABASE: "1"@REDIS_DATABASE: "0"@' {} \;
find . -type f -name 'docker-compose.*' -exec sed -i 's@REDIS_SSL: "yes"@REDIS_SSL: "no"@' {} \;
+ find . -type f -name 'docker-compose.*' -exec sed -i 's@REDIS_TLS_ENABLED: "yes"@REDIS_TLS_ENABLED: "no"@' {} \;
+ find . -type f -name 'docker-compose.*' -exec sed -i 's@REDIS_SENTINEL_TLS_ENABLED: "yes"@REDIS_SENTINEL_TLS_ENABLED: "no"@' {} \;
+ find . -type f -name 'docker-compose.*' -exec sed -i 's@REDIS_TLS_PORT_NUMBER: "[0-9]*"@REDIS_TLS_PORT_NUMBER: "6379"@' {} \;
+ find . -type f -name 'docker-compose.*' -exec sed -i 's@REDIS_TLS_AUTH_CLIENTS: "no"@REDIS_TLS_AUTH_CLIENTS: "yes"@' {} \;
+ find . -type f -name 'docker-compose.*' -exec sed -i 's@REDIS_PASSWORD: ".*"@REDIS_PASSWORD: ""@' {} \;
+ find . -type f -name 'docker-compose.*' -exec sed -i 's@REDIS_SENTINEL_PASSWORD: ".*"@REDIS_SENTINEL_PASSWORD: ""@' {} \;
+ find . -type f -name 'docker-compose.*' -exec sed -i 's@REDIS_USERNAME: ".*"@REDIS_USERNAME: ""@' {} \;
+ find . -type f -name 'docker-compose.*' -exec sed -i 's@REDIS_SENTINEL_USERNAME: ".*"@REDIS_SENTINEL_USERNAME: ""@' {} \;
+ find . -type f -name 'docker-compose.*' -exec sed -i 's@REDIS_SENTINEL_HOSTS: ".*"@REDIS_SENTINEL_HOSTS: ""@' {} \;
else
- sudo rm -rf tls
sudo sed -i 's@USE_REVERSE_SCAN=.*$@USE_REVERSE_SCAN=no@' /etc/bunkerweb/variables.env
sudo sed -i 's@USE_ANTIBOT=.*$@USE_ANTIBOT=no@' /etc/bunkerweb/variables.env
sudo sed -i 's@REDIS_PORT=.*$@REDIS_PORT=6379@' /etc/bunkerweb/variables.env
@@ -109,8 +154,10 @@ cleanup_stack () {
unset REDIS_PORT
unset REDIS_DATABASE
unset REDIS_SSL
+ sudo systemctl stop redis
sudo killall redis-server
fi
+ sudo rm -rf acl tls
if [[ $end -eq 1 && $exit_code = 0 ]] ; then
return
fi
@@ -137,7 +184,13 @@ cleanup_stack () {
# Cleanup stack on exit
trap cleanup_stack EXIT
-for test in "activated" "reverse_scan" "antibot" "tweaked"
+tests="activated reverse_scan antibot tweaked ssl"
+
+if [ "$integration" == "docker" ] ; then
+ tests="$tests sentinel sentinel_tweaked" # TODO sentinel_ssl
+fi
+
+for test in $tests
do
if [ "$test" = "activated" ] ; then
echo "🧰 Running tests with redis with default values ..."
@@ -153,6 +206,7 @@ do
echo "🧰 Running tests with redis with antibot cookie activated ..."
if [ "$integration" == "docker" ] ; then
find . -type f -name 'docker-compose.*' -exec sed -i 's@USE_REVERSE_SCAN: "yes"@USE_REVERSE_SCAN: "no"@' {} \;
+
find . -type f -name 'docker-compose.*' -exec sed -i 's@USE_ANTIBOT: "no"@USE_ANTIBOT: "cookie"@' {} \;
else
sudo sed -i 's@USE_REVERSE_SCAN=.*$@USE_REVERSE_SCAN=no@' /etc/bunkerweb/variables.env
@@ -164,17 +218,65 @@ do
echo "🧰 Running tests with redis' settings tweaked ..."
if [ "$integration" == "docker" ] ; then
find . -type f -name 'docker-compose.*' -exec sed -i 's@USE_ANTIBOT: "cookie"@USE_ANTIBOT: "no"@' {} \;
+
find . -type f -name 'docker-compose.*' -exec sed -i 's@REDIS_PORT: "[0-9]*"@REDIS_PORT: "6380"@' {} \;
+ find . -type f -name 'docker-compose.*' -exec sed -i 's@REDIS_PORT_NUMBER: "[0-9]*"@REDIS_PORT_NUMBER: "6380"@' {} \;
+ find . -type f -name 'docker-compose.*' -exec sed -i 's@REDIS_MASTER_PORT_NUMBER: "[0-9]*"@REDIS_MASTER_PORT_NUMBER: "6380"@' {} \;
find . -type f -name 'docker-compose.*' -exec sed -i 's@REDIS_DATABASE: "0"@REDIS_DATABASE: "1"@' {} \;
- find . -type f -name 'docker-compose.*' -exec sed -i 's@REDIS_SSL: "no"@REDIS_SSL: "yes"@' {} \;
+ find . -type f -name 'docker-compose.*' -exec sed -i 's@REDIS_PASSWORD: ".*"@REDIS_PASSWORD: "secret"@' {} \;
+ find . -type f -name 'docker-compose.*' -exec sed -i 's@REDIS_USERNAME: ".*"@REDIS_USERNAME: "bunkerweb"@' {} \;
else
sudo sed -i 's@USE_ANTIBOT=.*$@USE_ANTIBOT=no@' /etc/bunkerweb/variables.env
sudo sed -i 's@REDIS_PORT=.*$@REDIS_PORT=6380@' /etc/bunkerweb/variables.env
sudo sed -i 's@REDIS_DATABASE=.*$@REDIS_DATABASE=1@' /etc/bunkerweb/variables.env
- sudo sed -i 's@REDIS_SSL=.*$@REDIS_SSL=yes@' /etc/bunkerweb/variables.env
+ sudo sed -i 's@REDIS_PASSWORD=.*$@REDIS_PASSWORD=secret@' /etc/bunkerweb/variables.env
+ sudo sed -i 's@REDIS_USERNAME=.*$@REDIS_USERNAME=bunkerweb@' /etc/bunkerweb/variables.env
unset USE_ANTIBOT
export REDIS_PORT="6380"
export REDIS_DATABASE="1"
+ export REDIS_PASSWORD="secret"
+ export REDIS_USERNAME="bunkerweb"
+
+ echo "🧰 Stopping redis ..."
+ sudo systemctl stop redis
+ # shellcheck disable=SC2181
+ if [ $? -ne 0 ] ; then
+ echo "🧰 Redis stop failed ❌"
+ exit 1
+ fi
+ echo "🧰 Redis stopped ✅"
+ echo "🧰 Starting redis with tweaked settings ..."
+ redis-server --port 6380 --requirepass secret --aclfile acl/redis.acl --daemonize yes
+ # shellcheck disable=SC2181
+ if [ $? -ne 0 ] ; then
+ echo "🧰 Redis start failed ❌"
+ exit 1
+ fi
+ echo "🧰 Redis started ✅"
+ fi
+ elif [ "$test" = "ssl" ] ; then
+ echo "🧰 Running tests with redis' ssl activated ..."
+ if [ "$integration" == "docker" ] ; then
+ find . -type f -name 'docker-compose.*' -exec sed -i 's@REDIS_PORT_NUMBER: "[0-9]*"@REDIS_PORT_NUMBER: "6379"@' {} \;
+ find . -type f -name 'docker-compose.*' -exec sed -i 's@REDIS_MASTER_PORT_NUMBER: "[0-9]*"@REDIS_MASTER_PORT_NUMBER: "6379"@' {} \;
+ find . -type f -name 'docker-compose.*' -exec sed -i 's@REDIS_DATABASE: "1"@REDIS_DATABASE: "0"@' {} \;
+ find . -type f -name 'docker-compose.*' -exec sed -i 's@REDIS_PASSWORD: ".*"@REDIS_PASSWORD: ""@' {} \;
+ find . -type f -name 'docker-compose.*' -exec sed -i 's@REDIS_USERNAME: ".*"@REDIS_USERNAME: ""@' {} \;
+
+ find . -type f -name 'docker-compose.*' -exec sed -i 's@REDIS_SSL: "no"@REDIS_SSL: "yes"@' {} \;
+ find . -type f -name 'docker-compose.*' -exec sed -i 's@REDIS_TLS_ENABLED: "no"@REDIS_TLS_ENABLED: "yes"@' {} \;
+ find . -type f -name 'docker-compose.*' -exec sed -i 's@REDIS_TLS_PORT_NUMBER: "[0-9]*"@REDIS_TLS_PORT_NUMBER: "6380"@' {} \;
+ find . -type f -name 'docker-compose.*' -exec sed -i 's@REDIS_TLS_AUTH_CLIENTS: "yes"@REDIS_TLS_AUTH_CLIENTS: "no"@' {} \;
+ else
+ sudo sed -i 's@REDIS_PORT=.*$@REDIS_PORT=6379@' /etc/bunkerweb/variables.env
+ sudo sed -i 's@REDIS_DATABASE=.*$@REDIS_DATABASE=0@' /etc/bunkerweb/variables.env
+ sudo sed -i 's@REDIS_PASSWORD=.*$@REDIS_PASSWORD=@' /etc/bunkerweb/variables.env
+ sudo sed -i 's@REDIS_USERNAME=.*$@REDIS_USERNAME=@' /etc/bunkerweb/variables.env
+ sudo sed -i 's@REDIS_SSL=.*$@REDIS_SSL=yes@' /etc/bunkerweb/variables.env
+ unset REDIS_PORT
+ unset REDIS_DATABASE
+ unset REDIS_PASSWORD
+ unset REDIS_USERNAME
export REDIS_SSL="yes"
echo "🧰 Stopping redis ..."
@@ -186,7 +288,7 @@ do
fi
echo "🧰 Redis stopped ✅"
echo "🧰 Starting redis with tweaked settings ..."
- redis-server --tls-port 6380 --port 0 --tls-cert-file tls/redis.pem --tls-key-file tls/redis.key --tls-ca-cert-file tls/ca.crt --tls-auth-clients no --daemonize yes
+ redis-server --tls-port 6379 --port 0 --tls-cert-file tls/redis.pem --tls-key-file tls/redis.key --tls-ca-cert-file tls/ca.crt --tls-auth-clients no --daemonize yes
# shellcheck disable=SC2181
if [ $? -ne 0 ] ; then
echo "🧰 Redis start failed ❌"
@@ -194,6 +296,45 @@ do
fi
echo "🧰 Redis started ✅"
fi
+ elif [ "$test" = "sentinel" ] ; then
+ echo "🧰 Running tests with redis' in sentinel mode ..."
+ find . -type f -name 'docker-compose.*' -exec sed -i 's@REDIS_PORT: "[0-9]*"@REDIS_PORT: "6379"@' {} \;
+ find . -type f -name 'docker-compose.*' -exec sed -i 's@REDIS_SSL: "yes"@REDIS_SSL: "no"@' {} \;
+ find . -type f -name 'docker-compose.*' -exec sed -i 's@REDIS_TLS_ENABLED: "yes"@REDIS_TLS_ENABLED: "no"@' {} \;
+ find . -type f -name 'docker-compose.*' -exec sed -i 's@REDIS_TLS_PORT_NUMBER: "[0-9]*"@REDIS_TLS_PORT_NUMBER: "6379"@' {} \;
+ find . -type f -name 'docker-compose.*' -exec sed -i 's@REDIS_TLS_AUTH_CLIENTS: "no"@REDIS_TLS_AUTH_CLIENTS: "yes"@' {} \;
+
+ find . -type f -name 'docker-compose.*' -exec sed -i 's@REDIS_SENTINEL_HOSTS: ".*"@REDIS_SENTINEL_HOSTS: "redis-bw-redis-sentinel-1:26379 redis-bw-redis-sentinel-2:26379 redis-bw-redis-sentinel-3:26379"@' {} \;
+ elif [ "$test" = "sentinel_tweaked" ] ; then
+ echo "🧰 Running tests with redis' in sentinel mode with tweaked settings ..."
+ find . -type f -name 'docker-compose.*' -exec sed -i 's@REDIS_PORT: "[0-9]*"@REDIS_PORT: "6380"@' {} \;
+ find . -type f -name 'docker-compose.*' -exec sed -i 's@REDIS_PORT_NUMBER: "[0-9]*"@REDIS_PORT_NUMBER: "6380"@' {} \;
+ find . -type f -name 'docker-compose.*' -exec sed -i 's@REDIS_MASTER_PORT_NUMBER: "[0-9]*"@REDIS_MASTER_PORT_NUMBER: "6380"@' {} \;
+ find . -type f -name 'docker-compose.*' -exec sed -i 's@REDIS_SENTINEL_PORT_NUMBER: "[0-9]*"@REDIS_SENTINEL_PORT_NUMBER: "26380"@' {} \;
+ find . -type f -name 'docker-compose.*' -exec sed -i 's@REDIS_DATABASE: "0"@REDIS_DATABASE: "1"@' {} \;
+ find . -type f -name 'docker-compose.*' -exec sed -i 's@REDIS_PASSWORD: ".*"@REDIS_PASSWORD: "secret"@' {} \;
+ find . -type f -name 'docker-compose.*' -exec sed -i 's@REDIS_SENTINEL_PASSWORD: ".*"@REDIS_SENTINEL_PASSWORD: "sentinel_secret"@' {} \;
+ find . -type f -name 'docker-compose.*' -exec sed -i 's@REDIS_USERNAME: ".*"@REDIS_USERNAME: "bunkerweb"@' {} \;
+ find . -type f -name 'docker-compose.*' -exec sed -i 's@REDIS_SENTINEL_USERNAME: ".*"@REDIS_SENTINEL_USERNAME: "bunkerweb_sentinel"@' {} \;
+ find . -type f -name 'docker-compose.*' -exec sed -i 's@REDIS_SENTINEL_HOSTS: ".*"@REDIS_SENTINEL_HOSTS: "redis-bw-redis-sentinel-1:26380 redis-bw-redis-sentinel-2:26380 redis-bw-redis-sentinel-3:26380"@' {} \;
+ elif [ "$test" = "sentinel_ssl" ] ; then
+ echo "🧰 Running tests with redis' in sentinel mode with ssl activated ..."
+ find . -type f -name 'docker-compose.*' -exec sed -i 's@REDIS_PORT: "[0-9]*"@REDIS_PORT: "6379"@' {} \;
+ find . -type f -name 'docker-compose.*' -exec sed -i 's@REDIS_PORT_NUMBER: "[0-9]*"@REDIS_PORT_NUMBER: "6379"@' {} \;
+ find . -type f -name 'docker-compose.*' -exec sed -i 's@REDIS_MASTER_PORT_NUMBER: "[0-9]*"@REDIS_MASTER_PORT_NUMBER: "6379"@' {} \;
+ find . -type f -name 'docker-compose.*' -exec sed -i 's@REDIS_SSL: "no"@REDIS_SSL: "yes"@' {} \;
+ find . -type f -name 'docker-compose.*' -exec sed -i 's@REDIS_DATABASE: "1"@REDIS_DATABASE: "0"@' {} \;
+ find . -type f -name 'docker-compose.*' -exec sed -i 's@REDIS_PASSWORD: ".*"@REDIS_PASSWORD: ""@' {} \;
+ find . -type f -name 'docker-compose.*' -exec sed -i 's@REDIS_USERNAME: ".*"@REDIS_USERNAME: ""@' {} \;
+
+ find . -type f -name 'docker-compose.*' -exec sed -i 's@REDIS_SSL: "no"@REDIS_SSL: "yes"@' {} \;
+ find . -type f -name 'docker-compose.*' -exec sed -i 's@REDIS_TLS_ENABLED: "no"@REDIS_TLS_ENABLED: "yes"@' {} \;
+ find . -type f -name 'docker-compose.*' -exec sed -i 's@REDIS_TLS_PORT_NUMBER: "[0-9]*"@REDIS_TLS_PORT_NUMBER: "6380"@' {} \;
+ find . -type f -name 'docker-compose.*' -exec sed -i 's@REDIS_SENTINEL_TLS_ENABLED: "no"@REDIS_SENTINEL_TLS_ENABLED: "yes"@' {} \;
+ find . -type f -name 'docker-compose.*' -exec sed -i 's@REDIS_SENTINEL_PORT_NUMBER: "[0-9]*"@REDIS_SENTINEL_PORT_NUMBER: "26379"@' {} \;
+ find . -type f -name 'docker-compose.*' -exec sed -i 's@REDIS_TLS_AUTH_CLIENTS: "yes"@REDIS_TLS_AUTH_CLIENTS: "no"@' {} \;
+ find . -type f -name 'docker-compose.*' -exec sed -i 's@REDIS_SENTINEL_TLS_AUTH_CLIENTS: "yes"@REDIS_SENTINEL_TLS_AUTH_CLIENTS: "no"@' {} \;
+ find . -type f -name 'docker-compose.*' -exec sed -i 's@REDIS_SENTINEL_HOSTS: ".*"@REDIS_SENTINEL_HOSTS: "redis-bw-redis-sentinel-1:26379 redis-bw-redis-sentinel-2:26379 redis-bw-redis-sentinel-3:26379"@' {} \;
fi
echo "🧰 Starting stack ..."
diff --git a/tests/core/reversescan/Dockerfile b/tests/core/reversescan/Dockerfile
index 901d9763f..9b8ffd2f6 100644
--- a/tests/core/reversescan/Dockerfile
+++ b/tests/core/reversescan/Dockerfile
@@ -1,4 +1,4 @@
-FROM python:3.12.1-alpine3.18@sha256:af0d8da43677e3000ebdf4045508d891a87e7bd2d3ec87bc6e40403be97291b8
+FROM python:3.12.1-alpine3.18@sha256:fb759579d60cfe1f70b110a27be95aaa7cf758d2fa21cf54fffb71c2ba3f8034
# Install firefox and geckodriver
RUN apk add --no-cache --virtual .build-deps curl grep zip wget && \
diff --git a/tests/core/reversescan/requirements.in b/tests/core/reversescan/requirements.in
index 4b2f52ce8..501c8402b 100644
--- a/tests/core/reversescan/requirements.in
+++ b/tests/core/reversescan/requirements.in
@@ -1,3 +1,3 @@
fastapi==0.109.0
requests==2.31.0
-uvicorn[standard]==0.25.0
+uvicorn[standard]==0.27.0
diff --git a/tests/core/reversescan/requirements.txt b/tests/core/reversescan/requirements.txt
index 865d07ddd..88b6cdf0c 100644
--- a/tests/core/reversescan/requirements.txt
+++ b/tests/core/reversescan/requirements.txt
@@ -281,9 +281,9 @@ pydantic-core==2.14.6 \
--hash=sha256:fd9e98b408384989ea4ab60206b8e100d8687da18b5c813c11e92fd8212a98e0 \
--hash=sha256:ffff855100bc066ff2cd3aa4a60bc9534661816b110f0243e59503ec2df38421
# via pydantic
-python-dotenv==1.0.0 \
- --hash=sha256:a8df96034aae6d2d50a4ebe8216326c61c3eb64836776504fcca410e5937a3ba \
- --hash=sha256:f5971a9226b701070a4bf2c38c89e5a3f0d64de8debda981d1db98583009122a
+python-dotenv==1.0.1 \
+ --hash=sha256:e324ee90a023d808f1959c46bcbc04446a10ced277783dc6ee09987c37ec10ca \
+ --hash=sha256:f7b63ef50f1b690dddf550d03497b66d609393b40b564ed0d674909a68ebf16a
# via uvicorn
pyyaml==6.0.1 \
--hash=sha256:04ac92ad1925b2cff1db0cfebffb6ffc43457495c9b3c39d3fcae417d7125dc5 \
@@ -315,6 +315,7 @@ pyyaml==6.0.1 \
--hash=sha256:8d4e9c88387b0f5c7d5f281e55304de64cf7f9c0021a3525bd3b1c542da3b0e4 \
--hash=sha256:9046c58c4395dff28dd494285c82ba00b546adfc7ef001486fbf0324bc174fba \
--hash=sha256:9eb6caa9a297fc2c2fb8862bc5370d0303ddba53ba97e71f08023b6cd73d16a8 \
+ --hash=sha256:a08c6f0fe150303c1c6b71ebcd7213c2858041a7e01975da3a99aed1e7a378ef \
--hash=sha256:a0cd17c15d3bb3fa06978b4e8958dcdc6e0174ccea823003a106c7d4d7899ac5 \
--hash=sha256:afd7e57eddb1a54f0f1a974bc4391af8bcce0b444685d936840f125cf046d5bd \
--hash=sha256:b1275ad35a5d18c62a7220633c913e1b42d44b46ee12554e5fd39c70a243d6a3 \
@@ -363,9 +364,9 @@ urllib3==2.1.0 \
--hash=sha256:55901e917a5896a349ff771be919f8bd99aff50b79fe58fec595eb37bbc56bb3 \
--hash=sha256:df7aa8afb0148fa78488e7899b2c59b5f4ffcfa82e6c54ccb9dd37c1d7b52d54
# via requests
-uvicorn==0.25.0 \
- --hash=sha256:6dddbad1d7ee0f5140aba5ec138ddc9612c5109399903828b4874c9937f009c2 \
- --hash=sha256:ce107f5d9bd02b4636001a77a4e74aab5e1e2b146868ebbad565237145af444c
+uvicorn==0.27.0 \
+ --hash=sha256:890b00f6c537d58695d3bb1f28e23db9d9e7a17cbcc76d7457c499935f933e24 \
+ --hash=sha256:c855578045d45625fd027367f7653d249f7c49f9361ba15cf9624186b26b8eb6
# via
# -r requirements.in
# uvicorn
diff --git a/tests/core/selfsigned/Dockerfile b/tests/core/selfsigned/Dockerfile
index fe3cea3e7..29c73e1f0 100644
--- a/tests/core/selfsigned/Dockerfile
+++ b/tests/core/selfsigned/Dockerfile
@@ -1,4 +1,4 @@
-FROM python:3.12.1-alpine3.18@sha256:af0d8da43677e3000ebdf4045508d891a87e7bd2d3ec87bc6e40403be97291b8
+FROM python:3.12.1-alpine3.18@sha256:fb759579d60cfe1f70b110a27be95aaa7cf758d2fa21cf54fffb71c2ba3f8034
WORKDIR /tmp
diff --git a/tests/core/selfsigned/requirements.in b/tests/core/selfsigned/requirements.in
index eb01b1c97..ac853abcc 100644
--- a/tests/core/selfsigned/requirements.in
+++ b/tests/core/selfsigned/requirements.in
@@ -1,2 +1,2 @@
-cryptography==41.0.7
+cryptography==42.0.0
requests==2.31.0
diff --git a/tests/core/selfsigned/requirements.txt b/tests/core/selfsigned/requirements.txt
index bdcac4ec1..1ce6d5c2e 100644
--- a/tests/core/selfsigned/requirements.txt
+++ b/tests/core/selfsigned/requirements.txt
@@ -154,30 +154,39 @@ charset-normalizer==3.3.2 \
--hash=sha256:fd1abc0d89e30cc4e02e4064dc67fcc51bd941eb395c502aac3ec19fab46b519 \
--hash=sha256:ff8fa367d09b717b2a17a052544193ad76cd49979c805768879cb63d9ca50561
# via requests
-cryptography==41.0.7 \
- --hash=sha256:079b85658ea2f59c4f43b70f8119a52414cdb7be34da5d019a77bf96d473b960 \
- --hash=sha256:09616eeaef406f99046553b8a40fbf8b1e70795a91885ba4c96a70793de5504a \
- --hash=sha256:13f93ce9bea8016c253b34afc6bd6a75993e5c40672ed5405a9c832f0d4a00bc \
- --hash=sha256:37a138589b12069efb424220bf78eac59ca68b95696fc622b6ccc1c0a197204a \
- --hash=sha256:3c78451b78313fa81607fa1b3f1ae0a5ddd8014c38a02d9db0616133987b9cdf \
- --hash=sha256:43f2552a2378b44869fe8827aa19e69512e3245a219104438692385b0ee119d1 \
- --hash=sha256:48a0476626da912a44cc078f9893f292f0b3e4c739caf289268168d8f4702a39 \
- --hash=sha256:49f0805fc0b2ac8d4882dd52f4a3b935b210935d500b6b805f321addc8177406 \
- --hash=sha256:5429ec739a29df2e29e15d082f1d9ad683701f0ec7709ca479b3ff2708dae65a \
- --hash=sha256:5a1b41bc97f1ad230a41657d9155113c7521953869ae57ac39ac7f1bb471469a \
- --hash=sha256:68a2dec79deebc5d26d617bfdf6e8aab065a4f34934b22d3b5010df3ba36612c \
- --hash=sha256:7a698cb1dac82c35fcf8fe3417a3aaba97de16a01ac914b89a0889d364d2f6be \
- --hash=sha256:841df4caa01008bad253bce2a6f7b47f86dc9f08df4b433c404def869f590a15 \
- --hash=sha256:90452ba79b8788fa380dfb587cca692976ef4e757b194b093d845e8d99f612f2 \
- --hash=sha256:928258ba5d6f8ae644e764d0f996d61a8777559f72dfeb2eea7e2fe0ad6e782d \
- --hash=sha256:af03b32695b24d85a75d40e1ba39ffe7db7ffcb099fe507b39fd41a565f1b157 \
- --hash=sha256:b640981bf64a3e978a56167594a0e97db71c89a479da8e175d8bb5be5178c003 \
- --hash=sha256:c5ca78485a255e03c32b513f8c2bc39fedb7f5c5f8535545bdc223a03b24f248 \
- --hash=sha256:c7f3201ec47d5207841402594f1d7950879ef890c0c495052fa62f58283fde1a \
- --hash=sha256:d5ec85080cce7b0513cfd233914eb8b7bbd0633f1d1703aa28d1dd5a72f678ec \
- --hash=sha256:d6c391c021ab1f7a82da5d8d0b3cee2f4b2c455ec86c8aebbc84837a631ff309 \
- --hash=sha256:e3114da6d7f95d2dee7d3f4eec16dacff819740bbab931aff8648cb13c5ff5e7 \
- --hash=sha256:f983596065a18a2183e7f79ab3fd4c475205b839e02cbc0efbbf9666c4b3083d
+cryptography==42.0.0 \
+ --hash=sha256:0a68bfcf57a6887818307600c3c0ebc3f62fbb6ccad2240aa21887cda1f8df1b \
+ --hash=sha256:146e971e92a6dd042214b537a726c9750496128453146ab0ee8971a0299dc9bd \
+ --hash=sha256:14e4b909373bc5bf1095311fa0f7fcabf2d1a160ca13f1e9e467be1ac4cbdf94 \
+ --hash=sha256:206aaf42e031b93f86ad60f9f5d9da1b09164f25488238ac1dc488334eb5e221 \
+ --hash=sha256:3005166a39b70c8b94455fdbe78d87a444da31ff70de3331cdec2c568cf25b7e \
+ --hash=sha256:324721d93b998cb7367f1e6897370644751e5580ff9b370c0a50dc60a2003513 \
+ --hash=sha256:33588310b5c886dfb87dba5f013b8d27df7ffd31dc753775342a1e5ab139e59d \
+ --hash=sha256:35cf6ed4c38f054478a9df14f03c1169bb14bd98f0b1705751079b25e1cb58bc \
+ --hash=sha256:3ca482ea80626048975360c8e62be3ceb0f11803180b73163acd24bf014133a0 \
+ --hash=sha256:56ce0c106d5c3fec1038c3cca3d55ac320a5be1b44bf15116732d0bc716979a2 \
+ --hash=sha256:5a217bca51f3b91971400890905a9323ad805838ca3fa1e202a01844f485ee87 \
+ --hash=sha256:678cfa0d1e72ef41d48993a7be75a76b0725d29b820ff3cfd606a5b2b33fda01 \
+ --hash=sha256:69fd009a325cad6fbfd5b04c711a4da563c6c4854fc4c9544bff3088387c77c0 \
+ --hash=sha256:6cf9b76d6e93c62114bd19485e5cb003115c134cf9ce91f8ac924c44f8c8c3f4 \
+ --hash=sha256:74f18a4c8ca04134d2052a140322002fef535c99cdbc2a6afc18a8024d5c9d5b \
+ --hash=sha256:85f759ed59ffd1d0baad296e72780aa62ff8a71f94dc1ab340386a1207d0ea81 \
+ --hash=sha256:87086eae86a700307b544625e3ba11cc600c3c0ef8ab97b0fda0705d6db3d4e3 \
+ --hash=sha256:8814722cffcfd1fbd91edd9f3451b88a8f26a5fd41b28c1c9193949d1c689dc4 \
+ --hash=sha256:8fedec73d590fd30c4e3f0d0f4bc961aeca8390c72f3eaa1a0874d180e868ddf \
+ --hash=sha256:9515ea7f596c8092fdc9902627e51b23a75daa2c7815ed5aa8cf4f07469212ec \
+ --hash=sha256:988b738f56c665366b1e4bfd9045c3efae89ee366ca3839cd5af53eaa1401bce \
+ --hash=sha256:a2a8d873667e4fd2f34aedab02ba500b824692c6542e017075a2efc38f60a4c0 \
+ --hash=sha256:bd7cf7a8d9f34cc67220f1195884151426ce616fdc8285df9054bfa10135925f \
+ --hash=sha256:bdce70e562c69bb089523e75ef1d9625b7417c6297a76ac27b1b8b1eb51b7d0f \
+ --hash=sha256:be14b31eb3a293fc6e6aa2807c8a3224c71426f7c4e3639ccf1a2f3ffd6df8c3 \
+ --hash=sha256:be41b0c7366e5549265adf2145135dca107718fa44b6e418dc7499cfff6b4689 \
+ --hash=sha256:c310767268d88803b653fffe6d6f2f17bb9d49ffceb8d70aed50ad45ea49ab08 \
+ --hash=sha256:c58115384bdcfe9c7f644c72f10f6f42bed7cf59f7b52fe1bf7ae0a622b3a139 \
+ --hash=sha256:c640b0ef54138fde761ec99a6c7dc4ce05e80420262c20fa239e694ca371d434 \
+ --hash=sha256:ca20550bb590db16223eb9ccc5852335b48b8f597e2f6f0878bbfd9e7314eb17 \
+ --hash=sha256:d97aae66b7de41cdf5b12087b5509e4e9805ed6f562406dfcf60e8481a9a28f8 \
+ --hash=sha256:e9326ca78111e4c645f7e49cbce4ed2f3f85e17b61a563328c85a5208cf34440
# via -r requirements.in
idna==3.6 \
--hash=sha256:9ecdbbd083b06798ae1e86adcbfe8ab1479cf864e4ee30fe4e46a003d12491ca \
diff --git a/tests/core/sessions/Dockerfile b/tests/core/sessions/Dockerfile
index e5e0eeed5..8392c38b5 100644
--- a/tests/core/sessions/Dockerfile
+++ b/tests/core/sessions/Dockerfile
@@ -1,4 +1,4 @@
-FROM python:3.12.1-alpine3.18@sha256:af0d8da43677e3000ebdf4045508d891a87e7bd2d3ec87bc6e40403be97291b8
+FROM python:3.12.1-alpine3.18@sha256:fb759579d60cfe1f70b110a27be95aaa7cf758d2fa21cf54fffb71c2ba3f8034
# Install firefox and geckodriver
RUN apk add --no-cache --virtual .build-deps curl grep zip wget && \
diff --git a/tests/core/sessions/requirements.in b/tests/core/sessions/requirements.in
index 49cb1341f..45ceb3f45 100644
--- a/tests/core/sessions/requirements.in
+++ b/tests/core/sessions/requirements.in
@@ -1,2 +1,2 @@
requests==2.31.0
-selenium==4.16.0
+selenium<4.17.0
diff --git a/tests/core/whitelist/Dockerfile b/tests/core/whitelist/Dockerfile
index fe3cea3e7..29c73e1f0 100644
--- a/tests/core/whitelist/Dockerfile
+++ b/tests/core/whitelist/Dockerfile
@@ -1,4 +1,4 @@
-FROM python:3.12.1-alpine3.18@sha256:af0d8da43677e3000ebdf4045508d891a87e7bd2d3ec87bc6e40403be97291b8
+FROM python:3.12.1-alpine3.18@sha256:fb759579d60cfe1f70b110a27be95aaa7cf758d2fa21cf54fffb71c2ba3f8034
WORKDIR /tmp
diff --git a/tests/core/whitelist/api/Dockerfile b/tests/core/whitelist/api/Dockerfile
index aba06a1e0..00c640d42 100644
--- a/tests/core/whitelist/api/Dockerfile
+++ b/tests/core/whitelist/api/Dockerfile
@@ -1,4 +1,4 @@
-FROM python:3.12.1-alpine3.18@sha256:af0d8da43677e3000ebdf4045508d891a87e7bd2d3ec87bc6e40403be97291b8
+FROM python:3.12.1-alpine3.18@sha256:fb759579d60cfe1f70b110a27be95aaa7cf758d2fa21cf54fffb71c2ba3f8034
WORKDIR /tmp
diff --git a/tests/core/whitelist/api/requirements.in b/tests/core/whitelist/api/requirements.in
index c70d8e9ca..01e8a7398 100644
--- a/tests/core/whitelist/api/requirements.in
+++ b/tests/core/whitelist/api/requirements.in
@@ -1,2 +1,2 @@
fastapi==0.109.0
-uvicorn[standard]==0.25.0
+uvicorn[standard]==0.27.0
diff --git a/tests/core/whitelist/api/requirements.txt b/tests/core/whitelist/api/requirements.txt
index 9f6ef8206..f64cba8e6 100644
--- a/tests/core/whitelist/api/requirements.txt
+++ b/tests/core/whitelist/api/requirements.txt
@@ -183,9 +183,9 @@ pydantic-core==2.14.6 \
--hash=sha256:fd9e98b408384989ea4ab60206b8e100d8687da18b5c813c11e92fd8212a98e0 \
--hash=sha256:ffff855100bc066ff2cd3aa4a60bc9534661816b110f0243e59503ec2df38421
# via pydantic
-python-dotenv==1.0.0 \
- --hash=sha256:a8df96034aae6d2d50a4ebe8216326c61c3eb64836776504fcca410e5937a3ba \
- --hash=sha256:f5971a9226b701070a4bf2c38c89e5a3f0d64de8debda981d1db98583009122a
+python-dotenv==1.0.1 \
+ --hash=sha256:e324ee90a023d808f1959c46bcbc04446a10ced277783dc6ee09987c37ec10ca \
+ --hash=sha256:f7b63ef50f1b690dddf550d03497b66d609393b40b564ed0d674909a68ebf16a
# via uvicorn
pyyaml==6.0.1 \
--hash=sha256:04ac92ad1925b2cff1db0cfebffb6ffc43457495c9b3c39d3fcae417d7125dc5 \
@@ -217,6 +217,7 @@ pyyaml==6.0.1 \
--hash=sha256:8d4e9c88387b0f5c7d5f281e55304de64cf7f9c0021a3525bd3b1c542da3b0e4 \
--hash=sha256:9046c58c4395dff28dd494285c82ba00b546adfc7ef001486fbf0324bc174fba \
--hash=sha256:9eb6caa9a297fc2c2fb8862bc5370d0303ddba53ba97e71f08023b6cd73d16a8 \
+ --hash=sha256:a08c6f0fe150303c1c6b71ebcd7213c2858041a7e01975da3a99aed1e7a378ef \
--hash=sha256:a0cd17c15d3bb3fa06978b4e8958dcdc6e0174ccea823003a106c7d4d7899ac5 \
--hash=sha256:afd7e57eddb1a54f0f1a974bc4391af8bcce0b444685d936840f125cf046d5bd \
--hash=sha256:b1275ad35a5d18c62a7220633c913e1b42d44b46ee12554e5fd39c70a243d6a3 \
@@ -257,9 +258,9 @@ typing-extensions==4.9.0 \
# pydantic-core
# starlette
# uvicorn
-uvicorn==0.25.0 \
- --hash=sha256:6dddbad1d7ee0f5140aba5ec138ddc9612c5109399903828b4874c9937f009c2 \
- --hash=sha256:ce107f5d9bd02b4636001a77a4e74aab5e1e2b146868ebbad565237145af444c
+uvicorn==0.27.0 \
+ --hash=sha256:890b00f6c537d58695d3bb1f28e23db9d9e7a17cbcc76d7457c499935f933e24 \
+ --hash=sha256:c855578045d45625fd027367f7653d249f7c49f9361ba15cf9624186b26b8eb6
# via
# -r requirements.in
# uvicorn
diff --git a/tests/core/whitelist/init/Dockerfile b/tests/core/whitelist/init/Dockerfile
index 337a70388..3048b84c5 100644
--- a/tests/core/whitelist/init/Dockerfile
+++ b/tests/core/whitelist/init/Dockerfile
@@ -1,4 +1,4 @@
-FROM python:3.12.1-alpine3.18@sha256:af0d8da43677e3000ebdf4045508d891a87e7bd2d3ec87bc6e40403be97291b8
+FROM python:3.12.1-alpine3.18@sha256:fb759579d60cfe1f70b110a27be95aaa7cf758d2fa21cf54fffb71c2ba3f8034
WORKDIR /tmp
diff --git a/tests/requirements.in b/tests/requirements.in
index c3b5ded76..31b38a291 100644
--- a/tests/requirements.in
+++ b/tests/requirements.in
@@ -1,3 +1,3 @@
-pyOpenSSL==23.3.0
+pyOpenSSL==24.0.0
pyyaml==6.0.1
requests==2.31.0
diff --git a/tests/requirements.txt b/tests/requirements.txt
index c28f9b3fa..9395f9c51 100644
--- a/tests/requirements.txt
+++ b/tests/requirements.txt
@@ -154,30 +154,39 @@ charset-normalizer==3.3.2 \
--hash=sha256:fd1abc0d89e30cc4e02e4064dc67fcc51bd941eb395c502aac3ec19fab46b519 \
--hash=sha256:ff8fa367d09b717b2a17a052544193ad76cd49979c805768879cb63d9ca50561
# via requests
-cryptography==41.0.7 \
- --hash=sha256:079b85658ea2f59c4f43b70f8119a52414cdb7be34da5d019a77bf96d473b960 \
- --hash=sha256:09616eeaef406f99046553b8a40fbf8b1e70795a91885ba4c96a70793de5504a \
- --hash=sha256:13f93ce9bea8016c253b34afc6bd6a75993e5c40672ed5405a9c832f0d4a00bc \
- --hash=sha256:37a138589b12069efb424220bf78eac59ca68b95696fc622b6ccc1c0a197204a \
- --hash=sha256:3c78451b78313fa81607fa1b3f1ae0a5ddd8014c38a02d9db0616133987b9cdf \
- --hash=sha256:43f2552a2378b44869fe8827aa19e69512e3245a219104438692385b0ee119d1 \
- --hash=sha256:48a0476626da912a44cc078f9893f292f0b3e4c739caf289268168d8f4702a39 \
- --hash=sha256:49f0805fc0b2ac8d4882dd52f4a3b935b210935d500b6b805f321addc8177406 \
- --hash=sha256:5429ec739a29df2e29e15d082f1d9ad683701f0ec7709ca479b3ff2708dae65a \
- --hash=sha256:5a1b41bc97f1ad230a41657d9155113c7521953869ae57ac39ac7f1bb471469a \
- --hash=sha256:68a2dec79deebc5d26d617bfdf6e8aab065a4f34934b22d3b5010df3ba36612c \
- --hash=sha256:7a698cb1dac82c35fcf8fe3417a3aaba97de16a01ac914b89a0889d364d2f6be \
- --hash=sha256:841df4caa01008bad253bce2a6f7b47f86dc9f08df4b433c404def869f590a15 \
- --hash=sha256:90452ba79b8788fa380dfb587cca692976ef4e757b194b093d845e8d99f612f2 \
- --hash=sha256:928258ba5d6f8ae644e764d0f996d61a8777559f72dfeb2eea7e2fe0ad6e782d \
- --hash=sha256:af03b32695b24d85a75d40e1ba39ffe7db7ffcb099fe507b39fd41a565f1b157 \
- --hash=sha256:b640981bf64a3e978a56167594a0e97db71c89a479da8e175d8bb5be5178c003 \
- --hash=sha256:c5ca78485a255e03c32b513f8c2bc39fedb7f5c5f8535545bdc223a03b24f248 \
- --hash=sha256:c7f3201ec47d5207841402594f1d7950879ef890c0c495052fa62f58283fde1a \
- --hash=sha256:d5ec85080cce7b0513cfd233914eb8b7bbd0633f1d1703aa28d1dd5a72f678ec \
- --hash=sha256:d6c391c021ab1f7a82da5d8d0b3cee2f4b2c455ec86c8aebbc84837a631ff309 \
- --hash=sha256:e3114da6d7f95d2dee7d3f4eec16dacff819740bbab931aff8648cb13c5ff5e7 \
- --hash=sha256:f983596065a18a2183e7f79ab3fd4c475205b839e02cbc0efbbf9666c4b3083d
+cryptography==42.0.0 \
+ --hash=sha256:0a68bfcf57a6887818307600c3c0ebc3f62fbb6ccad2240aa21887cda1f8df1b \
+ --hash=sha256:146e971e92a6dd042214b537a726c9750496128453146ab0ee8971a0299dc9bd \
+ --hash=sha256:14e4b909373bc5bf1095311fa0f7fcabf2d1a160ca13f1e9e467be1ac4cbdf94 \
+ --hash=sha256:206aaf42e031b93f86ad60f9f5d9da1b09164f25488238ac1dc488334eb5e221 \
+ --hash=sha256:3005166a39b70c8b94455fdbe78d87a444da31ff70de3331cdec2c568cf25b7e \
+ --hash=sha256:324721d93b998cb7367f1e6897370644751e5580ff9b370c0a50dc60a2003513 \
+ --hash=sha256:33588310b5c886dfb87dba5f013b8d27df7ffd31dc753775342a1e5ab139e59d \
+ --hash=sha256:35cf6ed4c38f054478a9df14f03c1169bb14bd98f0b1705751079b25e1cb58bc \
+ --hash=sha256:3ca482ea80626048975360c8e62be3ceb0f11803180b73163acd24bf014133a0 \
+ --hash=sha256:56ce0c106d5c3fec1038c3cca3d55ac320a5be1b44bf15116732d0bc716979a2 \
+ --hash=sha256:5a217bca51f3b91971400890905a9323ad805838ca3fa1e202a01844f485ee87 \
+ --hash=sha256:678cfa0d1e72ef41d48993a7be75a76b0725d29b820ff3cfd606a5b2b33fda01 \
+ --hash=sha256:69fd009a325cad6fbfd5b04c711a4da563c6c4854fc4c9544bff3088387c77c0 \
+ --hash=sha256:6cf9b76d6e93c62114bd19485e5cb003115c134cf9ce91f8ac924c44f8c8c3f4 \
+ --hash=sha256:74f18a4c8ca04134d2052a140322002fef535c99cdbc2a6afc18a8024d5c9d5b \
+ --hash=sha256:85f759ed59ffd1d0baad296e72780aa62ff8a71f94dc1ab340386a1207d0ea81 \
+ --hash=sha256:87086eae86a700307b544625e3ba11cc600c3c0ef8ab97b0fda0705d6db3d4e3 \
+ --hash=sha256:8814722cffcfd1fbd91edd9f3451b88a8f26a5fd41b28c1c9193949d1c689dc4 \
+ --hash=sha256:8fedec73d590fd30c4e3f0d0f4bc961aeca8390c72f3eaa1a0874d180e868ddf \
+ --hash=sha256:9515ea7f596c8092fdc9902627e51b23a75daa2c7815ed5aa8cf4f07469212ec \
+ --hash=sha256:988b738f56c665366b1e4bfd9045c3efae89ee366ca3839cd5af53eaa1401bce \
+ --hash=sha256:a2a8d873667e4fd2f34aedab02ba500b824692c6542e017075a2efc38f60a4c0 \
+ --hash=sha256:bd7cf7a8d9f34cc67220f1195884151426ce616fdc8285df9054bfa10135925f \
+ --hash=sha256:bdce70e562c69bb089523e75ef1d9625b7417c6297a76ac27b1b8b1eb51b7d0f \
+ --hash=sha256:be14b31eb3a293fc6e6aa2807c8a3224c71426f7c4e3639ccf1a2f3ffd6df8c3 \
+ --hash=sha256:be41b0c7366e5549265adf2145135dca107718fa44b6e418dc7499cfff6b4689 \
+ --hash=sha256:c310767268d88803b653fffe6d6f2f17bb9d49ffceb8d70aed50ad45ea49ab08 \
+ --hash=sha256:c58115384bdcfe9c7f644c72f10f6f42bed7cf59f7b52fe1bf7ae0a622b3a139 \
+ --hash=sha256:c640b0ef54138fde761ec99a6c7dc4ce05e80420262c20fa239e694ca371d434 \
+ --hash=sha256:ca20550bb590db16223eb9ccc5852335b48b8f597e2f6f0878bbfd9e7314eb17 \
+ --hash=sha256:d97aae66b7de41cdf5b12087b5509e4e9805ed6f562406dfcf60e8481a9a28f8 \
+ --hash=sha256:e9326ca78111e4c645f7e49cbce4ed2f3f85e17b61a563328c85a5208cf34440
# via pyopenssl
idna==3.6 \
--hash=sha256:9ecdbbd083b06798ae1e86adcbfe8ab1479cf864e4ee30fe4e46a003d12491ca \
@@ -187,9 +196,9 @@ pycparser==2.21 \
--hash=sha256:8ee45429555515e1f6b185e78100aea234072576aa43ab53aefcae078162fca9 \
--hash=sha256:e644fdec12f7872f86c58ff790da456218b10f863970249516d60a5eaca77206
# via cffi
-pyopenssl==23.3.0 \
- --hash=sha256:6756834481d9ed5470f4a9393455154bc92fe7a64b7bc6ee2c804e78c52099b2 \
- --hash=sha256:6b2cba5cc46e822750ec3e5a81ee12819850b11303630d575e98108a079c2b12
+pyopenssl==24.0.0 \
+ --hash=sha256:6aa33039a93fffa4563e655b61d11364d01264be8ccb49906101e02a334530bf \
+ --hash=sha256:ba07553fb6fd6a7a2259adb9b84e12302a9a8a75c44046e8bb5d3e5ee887e3c3
# via -r requirements.in
pyyaml==6.0.1 \
--hash=sha256:04ac92ad1925b2cff1db0cfebffb6ffc43457495c9b3c39d3fcae417d7125dc5 \
@@ -221,6 +230,7 @@ pyyaml==6.0.1 \
--hash=sha256:8d4e9c88387b0f5c7d5f281e55304de64cf7f9c0021a3525bd3b1c542da3b0e4 \
--hash=sha256:9046c58c4395dff28dd494285c82ba00b546adfc7ef001486fbf0324bc174fba \
--hash=sha256:9eb6caa9a297fc2c2fb8862bc5370d0303ddba53ba97e71f08023b6cd73d16a8 \
+ --hash=sha256:a08c6f0fe150303c1c6b71ebcd7213c2858041a7e01975da3a99aed1e7a378ef \
--hash=sha256:a0cd17c15d3bb3fa06978b4e8958dcdc6e0174ccea823003a106c7d4d7899ac5 \
--hash=sha256:afd7e57eddb1a54f0f1a974bc4391af8bcce0b444685d936840f125cf046d5bd \
--hash=sha256:b1275ad35a5d18c62a7220633c913e1b42d44b46ee12554e5fd39c70a243d6a3 \
diff --git a/tests/ui/Dockerfile b/tests/ui/Dockerfile
index 6d17f25f4..fd11d693c 100644
--- a/tests/ui/Dockerfile
+++ b/tests/ui/Dockerfile
@@ -1,4 +1,4 @@
-FROM python:3.12.1-alpine3.18@sha256:af0d8da43677e3000ebdf4045508d891a87e7bd2d3ec87bc6e40403be97291b8
+FROM python:3.12.1-alpine3.18@sha256:fb759579d60cfe1f70b110a27be95aaa7cf758d2fa21cf54fffb71c2ba3f8034
# Install firefox and geckodriver
RUN apk add --no-cache --virtual .build-deps curl grep zip wget && \
diff --git a/tests/ui/main.py b/tests/ui/main.py
index 393786506..962c1ded6 100644
--- a/tests/ui/main.py
+++ b/tests/ui/main.py
@@ -4,6 +4,7 @@ from functools import partial
from os import getenv, listdir, sep
from os.path import join
from pathlib import Path
+from random import randint
from time import sleep
from traceback import format_exc
from typing import List, Union
@@ -1186,131 +1187,127 @@ location /hello {
sleep(3)
- print("The cache file content is correct, trying logs page ...", flush=True)
+ print("The cache file content is correct, trying reporting page ...", flush=True)
- access_page(driver, driver_wait, "/html/body/aside[1]/div[1]/div[3]/ul/li[8]/a", "logs")
+ get(f"http://www.example.com{ui_url}/home?id=/etc/passwd")
- ### LOGS PAGE
+ access_page(driver, driver_wait, "/html/body/aside[1]/div[1]/div[3]/ul/li[8]/a", "reports")
- print("Selecting correct instance ...", flush=True)
+ ### REPORTS PAGE
- assert_button_click(driver, "//button[@data-logs-setting-select='instances']")
+ print("Trying to filter the reports ...", flush=True)
- instances = safe_get_element(
- driver,
- By.XPATH,
- "//div[@data-logs-setting-select-dropdown='instances']/button",
- multiple=True,
- )
+ reports_list = safe_get_element(driver, By.XPATH, "//ul[@data-reports-list='']/li", multiple=True)
- first_instance = instances[0].text
-
- if len(instances) == 0:
- print("No instances found, exiting ...", flush=True)
+ if not reports_list:
+ print("No reports found, exiting ...", flush=True)
exit(1)
- assert_button_click(driver, instances[0])
- assert_button_click(driver, safe_get_element(driver, By.ID, "submit-data"))
-
- sleep(3)
-
- logs_list = safe_get_element(driver, By.XPATH, "//ul[@data-logs-list='']/li", multiple=True)
-
- if len(logs_list) == 0:
- print("No logs found, exiting ...", flush=True)
- exit(1)
-
- print("Logs found, trying auto refresh ...", flush=True)
-
- assert_button_click(driver, safe_get_element(driver, By.ID, "live-update"))
- assert_button_click(driver, safe_get_element(driver, By.ID, "submit-live"))
-
- sleep(3)
-
- if len(logs_list) == len(
- safe_get_element(
- driver,
- By.XPATH,
- "//ul[@data-logs-list='']/li[not(contains(@class, 'hidden'))]",
- multiple=True,
- )
- ):
- print("Auto refresh is not working, exiting ...", flush=True)
- exit(1)
-
- print("Auto refresh is working, deactivating it ...", flush=True)
-
- assert_button_click(driver, safe_get_element(driver, By.ID, "live-update"))
- assert_button_click(driver, safe_get_element(driver, By.ID, "submit-data"))
-
- sleep(3)
-
- logs_list = safe_get_element(driver, By.XPATH, "//ul[@data-logs-list='']/li", multiple=True)
-
- print("Trying filters ...", flush=True)
-
filter_input = safe_get_element(driver, By.ID, "keyword")
+ filter_input.send_keys("abcde")
- filter_input.send_keys("gen")
+ with suppress(TimeoutException):
+ WebDriverWait(driver, 2).until(
+ EC.presence_of_element_located(
+ (
+ By.XPATH,
+ "//ul[@data-reports-list='']/li[not(contains(@class, 'hidden'))]",
+ )
+ )
+ )
+ print("The keyword filter is not working, exiting ...", flush=True)
+ exit(1)
+
+ print("The reports have been filtered, trying bans page ...", flush=True)
+
+ ### BANS PAGE
+
+ access_page(driver, driver_wait, "/html/body/aside[1]/div[1]/div[3]/ul/li[9]/a", "bans")
+
+ try:
+ safe_get_element(driver, By.XPATH, "/html/body/main/div/div[2]/div/h5", error=True)
+ except TimeoutException:
+ print("Bans present even though they shouldn't be, exiting ...", flush=True)
+ exit(1)
+
+ print("No bans found, as expected, trying to add a ban ...", flush=True)
+
+ assert_button_click(driver, "//button[@data-add-ban='']")
+
+ try:
+ WebDriverWait(driver, 2).until(
+ EC.presence_of_element_located(
+ (
+ By.XPATH,
+ "//ul[@data-bans-add-ban-list='']/li",
+ )
+ )
+ )
+ except TimeoutException:
+ print("No bans found, exiting ...", flush=True)
+ exit(1)
+
+ assert_button_click(driver, "//button[@data-add-ban-delete-all-item='']")
+
+ with suppress(TimeoutException):
+ WebDriverWait(driver, 2).until(
+ EC.presence_of_element_located(
+ (
+ By.XPATH,
+ "//ul[@data-bans-add-ban-list='']/li",
+ )
+ )
+ )
+ print("Bans present even though they shouldn't be, exiting ...", flush=True)
+ exit(1)
+
+ print("No bans found, as expected, trying to add multiple bans ...", flush=True)
+
+ add_entry_button = safe_get_element(driver, By.XPATH, "//button[@data-ban-add-new='']")
+
+ assert_button_click(driver, add_entry_button)
+
+ ip_input = safe_get_element(driver, By.ID, "ip-1")
+ ip_input.send_keys(f"127.0.0.{randint(10, 122)}")
sleep(3)
- if len(logs_list) == len(
- safe_get_element(
- driver,
- By.XPATH,
- "//ul[@data-logs-list='']/li[not(contains(@class, 'hidden'))]",
- multiple=True,
- )
- ):
- print("The keyword filter is not working, exiting ...", flush=True)
+ assert_button_click(driver, add_entry_button)
+
+ ip_input = safe_get_element(driver, By.ID, "ip-2")
+ ip_input.send_keys(f"127.0.0.{randint(123, 255)}")
+
+ access_page(driver, driver_wait, "//button[@data-bans-modal-submit='']", "bans")
+
+ try:
+ entries = safe_get_element(driver, By.XPATH, "//ul[@data-bans-list='']/li", multiple=True, error=True)
+ except TimeoutException:
+ print("No ban found, exiting ...", flush=True)
exit(1)
- filter_input.clear()
-
- print("Keyword filter is working, trying type filter ...", flush=True)
-
- assert_button_click(driver, "//button[@data-logs-setting-select='types']")
-
- assert_button_click(
- driver,
- "//div[@data-logs-setting-select-dropdown='types']/button[@value='warn']",
- )
-
- if len(logs_list) == len(
- safe_get_element(
- driver,
- By.XPATH,
- "//ul[@data-logs-list='']/li[not(contains(@class, 'hidden'))]",
- multiple=True,
- )
- ):
- print("The keyword filter is not working, exiting ...", flush=True)
+ if len(entries) != 2:
+ print("The bans are present but there should be 2, exiting ...", flush=True)
exit(1)
- assert_button_click(driver, "//button[@data-logs-setting-select='types']")
+ print("Bans found, trying to delete them ...", flush=True)
- assert_button_click(
- driver,
- "//div[@data-logs-setting-select-dropdown='types']/button[@value='all']",
- )
+ assert_button_click(driver, "//input[@id='ban-item-2']")
- print("Type filter is working, trying to filter by date ...", flush=True)
+ access_page(driver, driver_wait, "//button[@data-unban-btn='']", "bans")
- current_date = datetime.now()
- resp = get(
- f"http://www.example.com{ui_url}/logs/{first_instance}?from_date={int(current_date.timestamp() - 86400000)}&to_date={int((current_date - timedelta(days=1)).timestamp())}",
- headers={"Host": "www.example.com", "User-Agent": driver.execute_script("return navigator.userAgent;")},
- cookies={"session": driver.get_cookies()[0]["value"]},
- )
-
- if len(resp.json()["logs"]) != 0:
- print("The date filter is not working, exiting ...", flush=True)
+ try:
+ entries = safe_get_element(driver, By.XPATH, "//ul[@data-bans-list='']/li", multiple=True, error=True)
+ except TimeoutException:
+ print("No bans found, exiting ...", flush=True)
exit(1)
- print("Date filter is working, trying jobs page ...", flush=True)
+ if len(entries) != 1:
+ print("The bans are present but there should be 1, exiting ...", flush=True)
+ exit(1)
- access_page(driver, driver_wait, "/html/body/aside[1]/div[1]/div[3]/ul/li[9]/a", "jobs")
+ print("Ban deleted successfully, trying jobs page ...", flush=True)
+
+ access_page(driver, driver_wait, "/html/body/aside[1]/div[1]/div[3]/ul/li[10]/a", "jobs")
### JOBS PAGE
@@ -1441,7 +1438,129 @@ location /hello {
print("The cache download is not working, exiting ...", flush=True)
exit(1)
- print("Cache download is working, trying account page ...", flush=True)
+ print("Jobs cache download is working, trying logs page ...", flush=True)
+
+ access_page(driver, driver_wait, "/html/body/aside[1]/div[1]/div[3]/ul/li[11]/a", "logs")
+
+ ### LOGS PAGE
+
+ print("Selecting correct instance ...", flush=True)
+
+ assert_button_click(driver, "//button[@data-logs-setting-select='instances']")
+
+ instances = safe_get_element(
+ driver,
+ By.XPATH,
+ "//div[@data-logs-setting-select-dropdown='instances']/button",
+ multiple=True,
+ )
+
+ first_instance = instances[0].text
+
+ if len(instances) == 0:
+ print("No instances found, exiting ...", flush=True)
+ exit(1)
+
+ assert_button_click(driver, instances[0])
+ assert_button_click(driver, safe_get_element(driver, By.ID, "submit-data"))
+
+ sleep(3)
+
+ logs_list = safe_get_element(driver, By.XPATH, "//ul[@data-logs-list='']/li", multiple=True)
+
+ if len(logs_list) == 0:
+ print("No logs found, exiting ...", flush=True)
+ exit(1)
+
+ print("Logs found, trying auto refresh ...", flush=True)
+
+ assert_button_click(driver, safe_get_element(driver, By.ID, "live-update"))
+ assert_button_click(driver, safe_get_element(driver, By.ID, "submit-live"))
+
+ sleep(3)
+
+ if len(logs_list) == len(
+ safe_get_element(
+ driver,
+ By.XPATH,
+ "//ul[@data-logs-list='']/li[not(contains(@class, 'hidden'))]",
+ multiple=True,
+ )
+ ):
+ print("Auto refresh is not working, exiting ...", flush=True)
+ exit(1)
+
+ print("Auto refresh is working, deactivating it ...", flush=True)
+
+ assert_button_click(driver, safe_get_element(driver, By.ID, "live-update"))
+ assert_button_click(driver, safe_get_element(driver, By.ID, "submit-data"))
+
+ sleep(3)
+
+ logs_list = safe_get_element(driver, By.XPATH, "//ul[@data-logs-list='']/li", multiple=True)
+
+ print("Trying filters ...", flush=True)
+
+ filter_input = safe_get_element(driver, By.ID, "keyword")
+
+ filter_input.send_keys("gen")
+
+ sleep(3)
+
+ if len(logs_list) == len(
+ safe_get_element(
+ driver,
+ By.XPATH,
+ "//ul[@data-logs-list='']/li[not(contains(@class, 'hidden'))]",
+ multiple=True,
+ )
+ ):
+ print("The keyword filter is not working, exiting ...", flush=True)
+ exit(1)
+
+ filter_input.clear()
+
+ print("Keyword filter is working, trying type filter ...", flush=True)
+
+ assert_button_click(driver, "//button[@data-logs-setting-select='types']")
+
+ assert_button_click(
+ driver,
+ "//div[@data-logs-setting-select-dropdown='types']/button[@value='warn']",
+ )
+
+ if len(logs_list) == len(
+ safe_get_element(
+ driver,
+ By.XPATH,
+ "//ul[@data-logs-list='']/li[not(contains(@class, 'hidden'))]",
+ multiple=True,
+ )
+ ):
+ print("The keyword filter is not working, exiting ...", flush=True)
+ exit(1)
+
+ assert_button_click(driver, "//button[@data-logs-setting-select='types']")
+
+ assert_button_click(
+ driver,
+ "//div[@data-logs-setting-select-dropdown='types']/button[@value='all']",
+ )
+
+ print("Type filter is working, trying to filter by date ...", flush=True)
+
+ current_date = datetime.now()
+ resp = get(
+ f"http://www.example.com{ui_url}/logs/{first_instance}?from_date={int((current_date - timedelta(weeks=1)).timestamp())}&to_date={int((current_date - timedelta(days=1)).timestamp())}",
+ headers={"Host": "www.example.com", "User-Agent": driver.execute_script("return navigator.userAgent;")},
+ cookies={"session": driver.get_cookies()[0]["value"]},
+ )
+
+ if len(resp.json()["logs"]) != 0:
+ print("The date filter is not working, exiting ...", flush=True)
+ exit(1)
+
+ print("Date filter is working, trying jobs page ...", flush=True)
access_page(driver, driver_wait, "/html/body/aside[1]/div[1]/div[2]/a", "account")
@@ -1700,6 +1819,8 @@ location /hello {
)
print("Successfully logged in without 2FA, tests are done, exiting ...", flush=True)
+ except KeyboardInterrupt:
+ pass
except SystemExit:
exit(1)
except:
diff --git a/tests/ui/requirements.in b/tests/ui/requirements.in
index c215e69bd..be5f526ba 100644
--- a/tests/ui/requirements.in
+++ b/tests/ui/requirements.in
@@ -1,3 +1,3 @@
pyotp==2.9.0
requests==2.31.0
-selenium==4.16.0
+selenium<4.17.0