Commit Graph
63 Commits
Author SHA1 Message Date
Michael Nightingale d73cdc7397 Stop treating routable special-purpose ranges as a local network 2026-09-08 22:44:12 +02:00
Michael Nightingale c01371a6af Refuse requests whose client a forwarded header hides 2026-09-08 22:44:12 +02:00
Michael Nightingale d8188b5428 Split subnet normalization out of ip_in_subnet 2026-09-08 22:44:12 +02:00
Michael Nightingale 7d9056736f Assert what the address tests were only evaluating 2026-09-08 22:44:12 +02:00
mnightingale e36d989ee5 Sanitize PP-values 2026-08-25 13:24:13 +02:00
mnightingale 35d5355f49 Replace CherryPy with Uvicorn and Starlette (#3550)
* Migrate web interface from CherryPy to Uvicorn/Starlette

Squashed rebase of feature/uvicorn (34 commits) onto develop, reconciled
with ~3 months of intervening develop changes.

Replaces the CherryPy webserver and request handling with Uvicorn/Starlette
across the API, web interface, RSS, config pages and related modules.

Reconciliation with develop during the rebase:
- api.py: kept develop's security/behaviour fixes (orphan path-traversal
  guard, expanded log redaction incl. host_whitelist and
  remote_label_replacement, get_dconfig single-return, get_retryable_jobs,
  connections default, translated NNTP test errors) on top of the Starlette
  request/response rewrite.
- interface.py: ported the RSS route handlers to develop's DB-backed
  RSSRepository API (process_feed, rss_repository / find_job_by_url /
  clear_feed / clear_downloaded / flag_downloaded).
- misc.py: kept develop's hachoir-based get_media_duration.
- requirements.txt: dropped the CherryPy stack, adopted develop's newer pins.

Also applied ruff --fix (PEP 604 unions, builtin generics) to align with
develop's lint config.

Verified: ruff check, black --check, and the affected test suites
(9413 passed, 1 skipped) all pass.

* Update starlette/uvicorn versions

* Fix race issues in global rss state

* Fix test race in server shutdown

The uvicorn migration turned /shutdown (and the shutdown API) into fire-and-forget: it spawned shutdown_program() in a background thread and replied immediately, whereas develop ran it synchronously and only replied once halt() had persisted all state. Because the module-scoped test teardown doesn't wait for the process to exit, the next module's clean_cache_dir wiped the shared cache dir (and reused the fixed port) while the previous instance was still saving state and holding the port — producing the three intermittent failures (deleted sabnzbd.log → "File log disabled or not found"; un-persisted [sorters] → KeyError; stale instance → missing wizard .quoteBlock).

* Fix robots and description, add favicon

* Remove remains of http basic auth

* Setup Starlette once configuration is available, fix static file relative cwd and url_base config

* abort_and_show_error when webserver fails to start

* Guard stopping webserver that never started

* Delegate XFF handling to ProxyHeadersMiddleware

* Merged params at request.state.params instead of modifying private apis

* Both shutdown routes share implementation and do not block event loop

* Run sync handlers via run_in_threadpool and facilitate eventual migration to async

* Pool database connections

* Online backup of database due to WAL changes

* Fix exception on None request.client (test clients or unix sockets)

* Fix flakey tests due to process not fully shutting down

* Restore X-Frame-Options behaviour via middleware

* Fix set_config_default with multiple keywords

* Remove broken logging call

* Restore api logging functionality

* Cache-Control: no-store

* Login only via POST

* Remove 401 (basic-auth) and add 404 handling via redirect

* Fix crash when shutdown not an int

* Use BaseRedirectResponse helper

* Remove trailing slashes from wizard routes

* URL helper, absolute URLs everywhere, fixes issues with nested navigation

* Fix scheduler adding multiple daysofweek

* Restore CherryPy api behaviour merging body with query params (body wins)

* Clearer documentation of get_request_params and request_params

* First stage supporting gradual api async

* Fix rss ajax consuming flash

* Restore access log functionality

* Hostname check in middleware

* Request logging in middleware

* Param parsing in middleware

* Security checks in middleware

* secured_expose is now purely route registration

* Lookup api handler once per request

* Fix flakey alert dialogs

* Trigger restart via BackgroundTask

* Restore CherryPy first param wins and get/post consistency

* Remove dead code

* Secure cookies based on protocol the client used

* Fix various issues with port_is_free

1. port_is_free answered the wrong question. It connect-probed ("is something answering?") rather than bind-probed ("can I bind?"). A port could report free and then kill startup at uvicorn's bind().
2. The bind-all remap crossed address families. :: was mapped to 127.0.0.1, probing IPv4 for an IPv6 bind — a regression against portend, which maps :: → ::1.
3. The call sites passed the wrong host. browserhost is a client-reachable address; the thing that has to be bindable is web_host.
4. Errors were swallowed. A bare except OSError hid gaierror, so an unresolvable host reported "free".
5. find_free_port had a port-0 trap. Under a bind-probe, currentport=0 always succeeds and returned 0 — the old failure sentinel. Now guarded, and None instead of 0.
6. Ports 80/443 were misdiagnosed. EACCES was folded into "occupied", producing ten futile probes and a panic claiming another program held the port. PermissionError now propagates to a dedicated panic explaining the actual remedies.
7. The tests were largely tautological. Three tests covering one branch, an IPv6 test with no IPv6 in it, a timeout test that never engaged the timeout, TOCTOU-prone fixed-range probes, no SO_REUSEADDR on the helper listener, and nothing asserting the property that matters — that "free" implies bindable.
8. A portability bug I introduced, then fixed. I'd baked Linux SO_REUSEADDR overlap semantics into four assertions; macOS differs. Now platform-aware, with the IPv6 regression re-covered by checking the socket family directly.

* Claim the bind address for uvicorn on startup, resolves "49" in err handling from cherrypy

* Rename function BaseRedirectResponse to base_redirect_response

* Restore error response on change web directory

* Add missing typings

* Fix return type of retry job for future types

* A better fix for xdist compatibility - test overwrote db_path

* Secure session cookies (rss flash)

* Inline or remove some functions

* Retry job futuretype behaviour

* Sneak a worksteal fix in

* Test and fix retry_job futuretype behaviour
2026-08-11 13:27:51 +01:00
mnightingale ec6ba3baae Speed up tests with pytest-xdist (#3546)
* Speed up tests with pytest-xdist

* Ignore request failures when the server disappeared

* Fix tests which modify module globals

* Fix lang change leaking

* Fix transaction compilation order breaking tests

* Always load a clean config and fix related tests

* No module globals

* Fix other test classes assigning module level by making calls

* Replace from sabnzbd.cfg import so monkeypatch works

* More global poisoning

* Fix dependant tests which worksteal breaks

* More global vars

* Drop loadscope until more failures are resolved

* Due to how pytest-xdist is implemented, the -s/--capture=no option does not work

* monkeypatch db_path

* Also patch startup_done

* loadscope
2026-08-10 17:44:18 +01:00
Safihre ba36e62695 Refactor Config object (#3552) 2026-08-10 09:24:53 +02:00
mnightingale dc5620a52c cgroup-aware memory limits for the article cache (#3528)
* Apply memory limits from cgroups

* Apply cgroup limits to article cache

* Fix this bug

* _physical_memory return None when undetermined

* Mark platform on test group

* Remove MemoryInfo dataclass

* Cap memory with reservation

* Keep the slightly broken 32 vs 64 bit code

* 512 *MEBI because the numbers look nicer
2026-07-31 09:42:47 +03:00
mnightingale 47a507f5a6 Fix flaky test_api_queue_sort test and to_unit at boundaries (#3522)
* Fix flaky sort test by comparing at the same resolution

* Fix consistency of values printed at reduced precision

* Replace the float-string roundtrip with rounding and adjust to next unit if required

* Comment styling
2026-07-28 17:59:47 +03:00
mnightingale 5c247e008c Fix test for when rarfile flags has_header_encryption after a failed password attempt (#3491) 2026-07-10 22:02:23 +02:00
mnightingale 8a92f4ac71 Verify RAR5 passwords when header encryption is not used (#3490)
* Verify RAR5 passwords when header encryption is not used

* Make flow a bit closer to rarfile

* Spelling

* Add note to trusting header verification

* Spelling

* Delegate to rarfile 4.3 where possible and cache rar*_s2k

* Explicit types instead of TypeVar

* Remove duplicate test and add a header encryption with correct password

* Verify after parse

* Rename method and explicit cache size

* Remove dead code

* Clearer verify after parse

* Performance early exit

* Clarify early exit

* Update comment, usually same password and salt

* Copy parse doc
2026-07-10 11:05:59 +02:00
Safihre e929a0c6b6 Use media duration for accurate sample detection (#3475)
* Use media duration for accurate sample detection

Enhances the `is_sample()` logic to reduce false positives for files
whose names contain "sample" or "proof" but are actually full-length
content.

Integrates the `hachoir` library to parse media files and extract their
duration. Files are only considered samples if their duration is less
than or equal to `SAMPLE_MAX_DURATION` (default 2 minutes).

If media duration cannot be determined (e.g., not a media file or
parsing fails), the detection falls back to the name-based approach.

* Refactor `is_sample` function to accept single path argument
2026-07-02 14:15:10 +02:00
Safihre 0950393b82 Correctly format tests based on new rules and remove star imports 2026-06-05 14:34:17 +02:00
Safihre 290f85ca1c Extend Cleanup List with filename and path pattern matching (#3413)
* Extend Cleanup List with filename and path pattern matching

Previously limited to cleaning up files based only on their extensions, the 'Cleanup List' now supports more flexible matching. Users can specify:
- Exact filenames (e.g., `Thumbs.db`)
- Wildcard filename patterns (e.g., `*.tmp`, `cleanup.*`)
- Relative path patterns (e.g., `images/*`, `*/test.jpg`)

This enhancement provides greater control and flexibility for automated post-processing cleanup.
2026-05-15 09:38:22 +02:00
mnightingale 2184964d78 Reduce time to test (#3412)
* Remove UI delays

* Everything using set_config, set_platform, or pyfakefs

* tmp_path

* Scroll to top seems unnecessary but make it wait until it's done

* Remove sleep from test_rss_basic_flow

* Remove sleeps from test_daemonizing

* Define pytest markers

* Reduce sleep in test_queue_repair

* Remove sleeps from clean_cache_dir

* Suppress failures to connect during startup

* Reduce cache sleeps

* Reduce sleeps checking app started

* Reduce sleep removing cache dir
2026-05-13 18:49:41 +02:00
Safihre 2122503762 Update copyright to 2026 2026-02-09 16:44:38 +01:00
Safihre a91e718ef5 Split nzbstuff into separate files for Article, NzbFile and NzbObject (#3221) 2025-12-09 21:21:51 +01:00
thezoggy dd0122865a bump copyright year (#3034) 2025-02-17 14:06:12 +01:00
Safihre ece4437c3a General changes to sanitization functions 2024-07-08 13:46:59 +02:00
Safihre b8fd9e6e31 Introduce bool_conv and fix ambiguous JSON retry value in history queue 2024-06-09 21:01:32 +02:00
Safihre f5efa5e93d Refactor handling of multiple comma separated values in the API 2024-02-20 16:23:33 +01:00
Safihre e89eba08c4 Add helper function is_none 2024-01-03 15:56:09 +01:00
thezoggy 9f6a9f9912 normalize and update copyright year 2024-01-02 09:42:17 +01:00
Safihre 7cbbff727f Remove (almost) all references to unused team@sabnzbd.org 2023-07-21 11:33:51 +02:00
jcfp 8525f60488 add optional xff header verification to check_access (#2611)
* add optional xff header verification to check_access

* make xff ip checking code more readable
2023-07-05 20:12:59 +02:00
Safihre b40220cb73 Only convert old-style sorters if they were enabled 2023-04-13 13:14:18 +02:00
jcfpandSafihre d651f8db34 Replace series/date/movie sorters with a generic one + season pack handling (#2461)
* replace series/date/movie sorters with a generic sorter

* fix test_eval_sort on windoze

* unbreak and de-uglify the fix

* add special setting for season pack sorting

* remove unused import

* replace series/date/movie sorters with a generic sorter

* fix test_eval_sort on windoze

* unbreak and de-uglify the fix

* add special setting for season pack sorting

* remove unused import

* correct type for sort_type entries

* standardize ui

* add visual hints for drag-n-drop

* move presets directly below sort string field

* replace hex with ascii letters to avoid random occurences of (cd|e)[0-9]+

* Some styling things

---------

Co-authored-by: Safihre <safihre@sabnzbd.org>
2023-03-06 22:13:12 +01:00
Safihre 6492cfb430 Update copyright year to 2023 2023-01-25 22:39:49 +01:00
Safihre ac6fc37c7d Small improvements of to_units and opts_to_pp 2022-09-16 06:50:48 +02:00
Safihre 2c972995d3 UnRar on Windows escapes quotes by double quoting them 2022-05-03 09:30:14 +02:00
Safihre d03eabe4d5 Black formatting update 2022-01-30 09:25:54 +01:00
Safihre fd28a8b427 Escape all HTML on template-based pages 2022-01-10 12:14:05 +01:00
Safihre 4d237c4328 Add unit tests for format_time_left 2022-01-08 09:49:44 +01:00
Safihre 9c7b61070b Update copyright year to 2022 2022-01-07 09:29:32 +01:00
Safihre dbef9af0df Add unit tests for Multipar and par2cmdline processing 2022-01-04 10:16:21 +01:00
Safihre 389a0d3afa Revert to using regex based sample detection
Closes #1964
2021-10-13 18:24:55 +02:00
jcfp 7d3907fa0e also test with (partially) exploded ipv4-mapped addresses (#1880) 2021-05-01 19:45:53 +02:00
jcfp 81a7a58299 support prefix and netmask for local_ranges (#1871)
* support prefix and netmask for local_ranges

* housekeeping
2021-04-29 08:35:46 +02:00
Safihre faf1a44944 Black formatting update 2021-04-26 10:52:11 +02:00
jcfp e249dbfc67 try sys.executable, but keep "python" as fallback (#1856) 2021-04-16 16:25:00 +02:00
jcfp 7096a785db fix bonjour with localhost, retire LOCALHOSTS constant (#1782)
* fix bonjour with localhost, retire LOCALHOSTS constant

* rename probablyipv[46] functions to is_ipv[46]_addr

* refuse to send ssdp description_xml to outsiders
2021-02-05 18:48:14 +01:00
Safihre ae30f89a2d Use basic restart for Windows binaries
Python 3.9 changed the output of Py_GetArgcArgv on Windows, causing the restart of the binaries to fail.
2021-01-21 20:55:31 +01:00
Safihre f0bfb08c2e Update copyright year to 2021 2021-01-03 20:43:19 +01:00
Safihre 9b71f8ca4b Use fully customizable date ranges for server graphs
Closes #1645
2020-11-28 21:35:03 +01:00
Safihre ee38441779 On Windows we do need startupinfo in POpen to prevent popups
https://forums.sabnzbd.org/viewtopic.php?f=11&t=24944
2020-09-03 15:29:58 +02:00
Safihre 521e2bd7aa Rename TOP_PRIORITY to FORCE_PRIORITY
To match the front-end naming.
2020-08-29 09:12:18 +02:00
Safihre 13d44d1ed9 Correct tests for build_and_run_command 2020-08-26 08:49:21 +02:00
Safihre d57ecd4eaa Add test for build_and_run_command 2020-08-25 15:27:27 +02:00
Safihre 7562444763 Convert functions to staticmethod if applicable 2020-08-14 22:45:34 +02:00