* Add SafeUnpickler to guard against pickle-attacks
* Harden pickle unpickler with explicit allowlist
The previous `SafeUnpickler` allowed any class from `sabnzbd.*` by wildcard, which could still enable deserialization attacks if a "gadget class" (e.g., with a malicious `__del__` method) was present within our own package.
This commit renames the class to `RestrictedUnpickler` and changes its logic to only allow classes explicitly defined in `_SAFE_GLOBALS`. This significantly enhances security by preventing the unpickling of any unlisted classes, including those from within `sabnzbd`. Adds `os.stat_result` and `sabnzbd.nzb.*` classes to the allowlist for compatibility.
* Implement article-level retry
* Remove count because bit_count is 3.10
* Fix errors importing files without article db
* Fix bookkeeping of bytes downloaded and on_disk status for complete existing files
* Legacy queue tests
* Bitmap types
* Add docs to Bitmap
* Match renamed files
* Add repair_job tests
* Need to remember failed state
* Only finish_import when required and defer setting on_disk state
* KISS
Closes#2735
* Fix RuntimeError from dict mutation in stop_idle_jobs (#3431)
Collecting exhausted articles into a snapshot list while holding
nzf.lock, then calling register_article outside the iteration.
This prevents RuntimeError when register_article -> nzf.remove_article
pops from nzf.articles (a dict) while stop_idle_jobs is iterating it.
The original code in fd3ece31c used `nzf.articles[:]` which was safe
when articles was a list. When 44d94226e changed articles to a dict
the protective copy was dropped, leaving bare dict iteration that
mutates mid-loop.
The collect-then-act pattern matches nzf_remove_list in nzb/object.py
and the empty-nzo list already used in stop_idle_jobs itself. It also
correctly calls register_article outside nzf.lock, consistent with its
own "not locked for performance" contract.
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
* Apply Black formatting to nzbqueue.py
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
* Soften comment per maintainer feedback
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
---------
Co-authored-by: Claude Sonnet 4.6 <noreply@anthropic.com>