Previous HTML stripping could allow malformed or unclosed tags to pass through, potentially leading to Cross-Site Scripting (XSS) vulnerabilities if completed by the browser.
This change updates the regex to aggressively remove all HTML tags, even incomplete ones. The `knockout-extensions.js` code also now universally escapes HTML, removing a potential bypass. New tests confirm this behavior.
Malformed RAR file metadata can raise exceptions other than `rarfile.Error` (e.g., `ValueError` on a bad seek). Catching these broader exceptions prevents the assembler from crashing during inspection.
The hachoir library is a large dependency (~5-10MB memory usage) that is exclusively used by the `get_media_duration` function. By moving its import statement inside this function, hachoir is only loaded when its functionality is actively needed, reducing the application's overall memory footprint.
On Windows, creating symbolic links requires either an elevated shell or Developer Mode. This introduces a runtime check to verify if symlinks can be created. Tests that rely on symlink creation are now skipped if this check fails, preventing unnecessary test failures in environments without the required permissions.
These tests rely on a specific behavior of '..' in paths involving symbolic links, which differs on Windows where '..' is collapsed before the filesystem resolves links.
Replaces `github.token` with `secrets.AUTOMATION_GITHUB_TOKEN` to provide consistent and appropriate permissions for automated tasks like creating pull requests.
* Guard the speed counters with their own lock so updates are not lost
* Update the speed counters without taking the Downloader lock
* Skip the downloader sleep once the loop rather than the connection is the limit
* Remove unused variable
Moves theme-specific styles into main CSS files for each interface,
leveraging `color-scheme` and `light-dark()` CSS functions. This
consolidates styling, reduces HTTP requests, and improves automatic
dark/light mode detection based on OS preferences.
Previously, UI access for login-bypassed clients relied on issuing a stateless "anonymous session" cookie to enable CSRF protection. This commit removes that cookie mechanism.
Instead, when the login is bypassed (e.g., for local clients without credentials), the CSRF token is now bound to a stable, internal "anonymous" identity. This maintains robust CSRF protection for browser interactions without requiring an explicit session cookie, simplifying overall session management.
* Watch whether the download directory keeps up with writes placed where they belong
* Default direct_decode on, refusing a sink while the destination is not keeping up
* Measure what the destination drains and report it as a rate
* Pace the downloader against the measured write rate rather than the cache level
* Handle SparseUnsupported and do not disable direct_write just because it's unsupported for a file
* Let sabctools carve the write totals into intervals instead of tracking them here
* sabctools 9.7.1
Instead of interpreting and translating common NNTP error messages (e.g., authentication failure, too many connections) into generic localized strings, this change passes the raw server response directly to the user. This provides more accurate and specific diagnostic information for troubleshooting server-related issues.
Closes#3563
* Add a session store that keeps web-UI logins in the admin folder
* Authenticate the web interface with session cookies and CSRF tokens
* Stop embedding the apikey in the web interface
* Cover the session, CSRF and apikey changes
Trigger the corresponding LinuxServer.io Docker image build (develop for
pre-releases, master for stable) after a SABnzbd release, ensuring the
Docker images are kept up-to-date.
The `mode` parameter in API calls enables specific behaviors and key bypasses (e.g., 'version', 'auth', NZB-key). Previously, this logic was applied universally by `check_apikey`. This change ensures such `mode`-based logic is only honored when accessing the dedicated `/api` endpoint, preventing potential API key bypasses on other web UI routes.
Prevent directory creation in `renamer` to overwrite `__ADMIN__`
Check the whole new path for `__ADMIN__` in `renamer`
Drop `__ADMIN__` from names that are allowed to have sub-directories
Resolve the path before checking it against `__ADMIN__`
* 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.
* Use sabctools.FileWriter for article writes
* Keep the FileWriter open on the NzbFile, bounded by an LRU
* Stream decoded articles straight to their file
* Fail the article, not the connection, when a streaming write fails
* Pause on a disk error from a streamed write
A full disk cannot be fixed by fetching the article again, so mirror the assembler
and pause instead of spending its retries and failing the job as incomplete.
* Treat an exhausted quota as a full disk
* Use sabctools 9.7.0
* Refuse unbracketed IPv6 addresses in the Host header
* Bracket the IPv6 client address logged with warnings
* Decide the Secure cookie attribute from the request scope
* Reproduce bug
* Let sanitize_filename keep par2 sub-directories
Par2 sets can store their files inside a folder, always using a forward slash as
separator no matter which platform created the set. We replaced that slash with an
underscore, so the name could never match what par2 called the file.
With allow_subdirs the separator is kept and every part is sanitized on its own.
The result stays local to the folder it is used in: empty parts, "." and ".." are
dropped, so neither a leading slash nor any amount of traversal can point outside.
* Write files into the sub-directory par2 names them in
The name from the par2 pack is what we already rename files to, but the separator
was stripped so the file landed flat with an underscore. Post-processing then had
to move it into place afterwards, which is how the volumes ended up somewhere the
unpacker did not look.
Assemble straight into the sub-directory instead. get_unique_filepath() creates the
folder and returns the name relative to the download folder, so nzf.filename now
holds that relative name. analyze_rar_filename() takes the basename, so a setname
still matches what rar_unpack() derives from a path with setname_from_path().
* Match existing files in sub-directories on retry
check_existing_files() listed the job folder without descending into it, so on a
retry the volumes par2 put in a folder of their own were never matched and got
downloaded again.
List the sub-directories too, skipping the admin folder, and match on the name
relative to the job folder. Rename bookkeeping is normalized to the platform
separator, par2 always reports a forward slash.
* Find rar sets in the job's sub-directories
* Wait for the direct unpacker to finish
* Update nzf.setname and nzf.vol after deobfuscating names
* Fix double extraction
* Ruff
* Only purge unconfigured rss feeds at startup
* Only perform remove obsolete actions if the feed was read
* Update seen_at so downloaded items are not removed while still in the feed
* Increase hardcoded retention to 7 days
Jobs are listed in the history output as soon as they enter the
post-processing queue, and a stopped job has its status set to Failed at
the very start of process_job. The duplicate alternative is only released
near the end of it, so waiting for the job to show up in the history as
failed does not guarantee the alternative was already released. The gap
is tiny when running serially, but wide enough to fail the test under the
load of pytest-xdist. Wait for the label to be dropped instead.
Also move the helpers shared by both adding-NZB test classes into a base
class in testhelper, so the clean tests no longer have to import the
other test module to copy its methods.
* 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
* 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
Adopt `frozenset` for extension collections to enable faster lookups and ensure immutability. Add explicit `utf-8` encoding to file reads to prevent locale-dependent issues when identifying text/NZB files. Optimize by caching results of `all_possible_extensions` to avoid redundant computations.
Adds `BasicConstraints` to the generated certificates for better compliance and explicitly marks them as non-CA. Changes the `SubjectAlternativeName` extension to non-critical, improving client compatibility. Improves robustness in SAN list generation and adds type hints for clarity.
Escapes dynamic data in the SSDP device description XML to prevent issues with special characters and improve robustness. Enhances code clarity and maintainability through explicit constructor parameters, type hints, and updated docstrings. Also adds debug logging for SSDP broadcast failures and renames the module-level singleton for better Python convention.
`SIGTERM` is an expected part of a clean shutdown.
Previously, the signal handler posted a log warning for any signal received.
This PR turns down the log level to info for `SIGTERM` (non-Windows only).
Tested:
% python3 -m venv venv
% source venv/bin/activate
% pip install -r dependencies.txt
% python3 -OO SABnzbd.py
In another terminal, ran `kill -TERM $PID`.
Confirmed in logs that log level was now set to `INFO`:
```
2026-08-05 08:37:10,296::INFO::[__init__:217] Signal 15 caught, saving and exiting...
```
Full logs:
https://gist.github.com/bhamiltoncx/2f8845b63c52e47fc4f00de263c21152
* 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
* Label schedule time, enable, and delete controls
* Use ARIA label for schedule enable control
---------
Co-authored-by: coopa11y <coopa11y@users.noreply.github.com>
* 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
* feat: add 'Sort by Remaining Size' queue sort option
Add a new 'remaining_bytes' sort field that sorts the queue by absolute
remaining bytes (bytes - bytes_tried), complementing the existing
'remaining' sort which uses percentage downloaded and the 'size' sort
which uses total bytes.
Changes:
- nzbqueue.py: add remaining_bytes sort field, fix update_sort_order()
to parse field+direction from config instead of hardcoding 'remaining'
- skintext.py: add Glitter-sortRemainingBytesAsc/Desc translation strings,
update auto_sort explanation text
- Glitter UI: add dropdown entries and JS handlers for both directions
- Config: add auto_sort options for remaining_bytes asc/desc
- Tests: parametrize remaining_bytes asc/desc against sizeleft slot field
* style: wrap long string for Black formatting
* fix: limit remaining-size sorting to ascending
---------
Co-authored-by: QuixThe2nd <QuixThe2nd@users.noreply.github.com>
When `DirScanner` is initialized on the main thread, `asyncio.new_event_loop()` can register its self-pipe as the process-wide signal wakeup FD. As the `DirScanner`'s loop runs and is closed on a separate thread, this registration would become stale, potentially breaking signal delivery during application shutdown. Explicitly unregistering the FD prevents this issue.
During NNTP server tests, detect high latency and low pipelining settings.
Provide a helpful warning to users to consider increasing their 'Articles per request'
setting to improve download speed.
Closes#3284
* RSS age rule
* Support years (y) and months (mo) and do not approximate durations in seconds
* Better handling of entries with no age
* Formatting
* Allow >=, =>, <=, and =< aliases
* Implement feedback
* Fix existing issue with From SxxEyy in default row
* Test unitless ages
Modernizes `get_rar_extension` to leverage the `rarfile` library's internal header parsing, significantly improving the robustness and reliability of RAR volume number and original extension detection.
The `rar_renamer` function in post-processing is also refactored for improved clarity and maintainability, including the extraction of a dedicated helper function for renaming and various code simplifications.
* 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
Modernizes Windows Registry interaction by leveraging `with` statements for automatic
key closure, improving resource management and preventing potential leaks.
Simplifies registry value operations (get, set, delete) and consistently defines
full key paths in `reg_info`, reducing boilerplate. Adds type hints to enhance
code readability and maintainability.
The previous method for detecting FAT filesystems on macOS relied on parsing `df` and `mount` command output, which is brittle and prone to issues with command output variations.
This change replaces the shell command parsing with a more robust and idiomatic approach using Foundation.framework's `NSURL` API. This directly queries the volume's localized format description, ensuring accurate identification of MS-DOS (FAT12/FAT16/FAT32) volumes while correctly distinguishing them from ExFAT.
Adds unit tests for the `isFAT` function to verify basic functionality and error handling.
Closes#3483
The previous smoke test only verified that the snap binary could be executed. This change enhances the CI workflow to confirm the SABnzbd web UI starts successfully and responds on its default port after snap installation, improving the robustness of the build pipeline.
The `dnslookup` and `public_ip` functions rely on a configured `selftest_host`. This change prevents unnecessary network attempts and provides explicit debug logging when the host is not set.
Closes#3485
Moves the `PYTHON_VERSION` environment variable to a global scope in `build_release.yml`. This ensures consistent Python versions across build jobs (Windows and macOS) and centralizes it for easier future updates (e.g., via Renovate).
* Add workflow for automated bundled tool updates
Introduces a GitHub Actions workflow to automatically check for new releases of unrar, 7-Zip, and par2cmdline-turbo. When new versions are found, it creates a pull request with the updated binaries for review.
* Use preinstalled 7Zip so we don't execute any downloaded executables
Leverage the preinstalled 7-Zip utility on GitHub Actions runners to
extract Windows UnRAR.exe and 7za.exe. This prevents executing internet executables with write-permission GH-token.
* Inline the unrar version detection
And rename to RAW_VERSION
* 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
Replaces the generic `SysTrayIconThread` base class with a dedicated `sabtraywin` module.
Added several optimizations and refactoring of the original sabtray code that was very ancient.
* Abort postproc rar unpacker if prompted for volume or to retry
* Skip empty but preserve trailing whitespace when not whole lines
* Strings and fail_msg for write error / retry
* Not necessary not pausing for volumes and will output "Cannot find volume" and be handled
* dont sleep it waits anyway
Adds security checks to `_api_delete_orphan` and `_api_add_orphan` endpoints
to ensure that operations are restricted strictly to the download directory.
This mitigates potential path traversal vulnerabilities, preventing
unauthorized file deletion or modification outside the intended scope.
Reported as GHSA-hxwh-mmrg-p8f5
Unsigned Windows binaries and installers are now uploaded with `archive: true` for release tags. This creates a "zip-in-zip" layout that SignPath requires for consuming artifacts.
* Track files during cleanup to prevent removing unrelated files
* Remove redundant path normalization
The `os.path.abspath` function already includes path normalization,
rendering the explicit call to `os.path.normpath` redundant
when used in conjunction. Removing it simplifies the code
without changing its behavior.
The `translations.yml` workflow now fetches `fetch-depth: 2` and uses `git show`
to detect if the current commit includes local `.po` file changes. If local
translation edits are present, `tx push --translation` is used; otherwise,
only `--source` is pushed. This prevents accidental overwrites of Transifex
translations with outdated local files when no `.po` changes were intended.
This commit also includes updated translations in various `.po` files and adds
guidance for translators to `po_to_json.py` for consistency.
* 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
All direct and transitive dependencies are now explicitly listed in
`requirements.txt` files, and `pip install` commands consistently use
`--no-dependencies`.
This approach ensures that only the specified versions are installed,
enhancing supply chain security and build reproducibility by preventing
automatic dependency resolution. The `--upgrade` flag was removed from
these installations as it is no longer necessary with fully pinned
dependencies.
The `INSTALL.txt` file has been removed, as all installation instructions are now exclusively maintained on the project wiki. This updates `README.md` and build artifacts to reflect this change.
Additionally, `COPYRIGHT.txt` has been updated to include a new active team member, streamline translation contributor credits, and provide a direct link to GNU licenses. A minor CSS adjustment for the mobile UI is also included.
This update improves the release workflow by:
* Configuring GitHub Actions `upload-artifact` to transfer files directly without unnecessary zipping, simplifying artifact retrieval for subsequent jobs.
* Integrating `pefile` to perform an Authenticode signature check on the Windows installer, ensuring all official releases are properly signed.
Updates the default number of connections from 8 to 16 in the server configuration and wizard UI templates. This change aims to improve performance for users who do not explicitly configure this setting.
Additionally, ensures the API server test function defaults to at least 1 connection when none is specified.
Relates to #3284
pytest 9.1 removed FormattedExcinfo from _pytest._code.code, which tavern still imports unconditionally, breaking test collection on Python 3.11+.
Reported upstream: https://github.com/taverntesting/tavern/issues/1054
* Support extracting tar files
* Set fail_msg when Python is too old
* Update error to "Unpacking failed, TAR support requires Python 3.12 or later", set per set/file, and don't regard as a failure if unsupported
* Update sabnzbd/newsunpack.py
Co-authored-by: Safihre <safihre@sabnzbd.org>
* Use UNWANTED_FILE_PERMISSIONS (stat.S_ISUID and stat.S_ISGID) are already removed by tar_filter but this is cleaner
* TAR extraction test including non-executable check
* ruff
* Skip executable check on Windows
* Remove helloworld.sh
* get_unique_filename
* Test path traversal, owner/group and permissions
* Fix duplicate file issues with one_folder
* Rename filter
---------
Co-authored-by: Safihre <safihre@sabnzbd.org>
Closes#2227
Beware that this causes extra CPU usage.
Claude has diagnosed:
What it almost certainly is: paint/raster cost of native form controls. Every refresh tick the progress bar width and text change, which invalidates a paint region spanning most of the row. Chrome re-rasterizes damaged tiles wholesale, and the selects sit in those tiles. A <select> — especially one with custom styling like ours, which knocks Chrome off the native-theme fast path — is much more expensive to rasterize than plain text, and there are 4 of them per row, re-painted every second while downloading. Rasterization runs on Chrome's compositor/raster threads, which is exactly the kind of cost that shows up in the browser Task Manager but is invisible to JS-side profiling (which is why my layout measurement showed no difference). Form controls also carry extra accessibility-tree bookkeeping on each DOM-adjacent change, which adds a little more.
Enhance installer and uninstaller logic to ensure more reliable operation:
- Properly stop, delete, and manage the Windows service during uninstall.
- Implement more robust process termination for SABnzbd.exe.
- Add checks to prevent accidental deletion of unrelated directories.
- Dynamically calculate and display the installed size in Add/Remove Programs.
- Correctly target user-specific settings during uninstallation.
Previously, restarting the frozen macOS application directly launched the raw binary in Terminal.app. This change uses `open -n` and the application's bundle path to ensure the app relaunches correctly as a graphical application, providing a clean environment and proper menu-bar context. Fixes#3455.
On Windows, `select()` has a hard limit of 512 connections. This change adds a check at startup to warn the user if their configured connections exceed this limit, preventing potential crashes.
Closes#3429
Adds custom managers to allow Renovate to detect and propose updates for the Python version used in the build workflow and the `SABCTOOLS_VERSION_REQUIRED` constant. Removes `sabctools` from the ignore list to enable these updates.
Refactors collection initializations and comprehensions to use more concise and idiomatic Python syntax, such as set literals (`{...}`) instead of `set([...])`, empty dictionary literals (`{}`) instead of `dict()`, and `dict.fromkeys` for `str.maketrans`.
Also removes unnecessary list creation within `any()` calls.
Adds an explicit check to prevent unnecessary rename operations when the target path is the same as the original file's path. This provides clearer debug logging and avoids redundant filesystem calls.
Closes#3449, #3442
Explicitly defines the structure and types for the `nzo_info` dictionary.
Also introduces `BadArticleType` as a `Literal` type and cleans up
`__init__.py` by removing internal saver classes from the public API.
* Sanitise host_whitelist and login/request IP addresses
* Keep json keys
* Remove all IPv4 and IPv6 from logs
* Less crazy remote label replacements
* Remove unused import
* Sanitise public ipv4/ipv6 and test
* Add loopback/link-local test cases
* Switch is_local_addr to is_lan_addr because the former allows user configuration of trusted addresses
* Remove prefix group, ip regex should be good enough
directory_is_writable_with_file() removed its fixed-name temp file in a
non-atomic exists/remove/open/remove sequence wrapped in a blanket
"except Exception: return False". If the test file was removed between the
write and the final os.remove (e.g. by a concurrent writability check), the
FileNotFoundError was swallowed and reported as "is not writable at all.
This blocks downloads." -- a false negative on a fully writable folder.
Make the result depend only on creating and writing the file; treat cleanup
as best-effort. Genuine write failures still return False, and the unicode
and special-character capability checks are unchanged.
Adds regression tests for the cleanup race and for a genuine write failure.
Addresses a runtime error encountered when using native union syntax (PEP 604) with `threading.Lock` and `RLock` in type hints. As factory functions, they cannot be directly used with `|` without `from __future__ import annotations`.
Tempora 5.9.0 introduced an incompatibility with jaraco.classes that caused issues. Downgrade to the previous stable version and prevent Renovate from automatically updating it again.
Closes#3441
Migrate to `A | B` syntax for unions (PEP 604) and introduce `typing.TypeAlias` for complex types, leveraging features available in Python 3.10+. This also updates `socket.timeout` to `TimeoutError` and adds `UP045` to Ruff ignores.
* 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>
Refines margins, paddings, and element positioning across various components to improve visual harmony and alignment with the modernized interface design.
This modernizes the theming architecture by defining core colors as CSS variables,
allowing themes like 'Night' to override them concisely. This approach improves
maintainability and removes dynamic styling previously handled by JavaScript.
* Match to previous RSS behaviour
* Cleanup logic due to normalisation
* Tests comparing 4.5.5 outcome
* Remove comment - fixed since 4.5.5
* Consistent types for prio, rule, season, and episode
* Rename matching_rule_index
* Fix type warnings
The Python plugin attempts to `pip install -U .` when `pyproject.toml`
is present. As SABnzbd is an application source tree and not a
pip-installable package, this temporarily hides `pyproject.toml`
during the build step to prevent an incorrect installation attempt.
The `os.access()` function can produce false negatives for directory writability, particularly in environments like NFS with UID mapping or root-squashing.
This change replaces the `os.access()` call with a direct I/O test (creating and deleting a temporary file) to ensure accurate and reliable verification of directory permissions.
Apply the table-header-progress-smaller class (25% width) to both queue and
history when compact layout is enabled, matching the behavior when extra columns
are shown. This provides more horizontal space for longer NZB titles.
Fixes#3414
Configures `concurrency` for the build, snap, and integration testing workflows. This prevents multiple concurrent runs of the same workflow on the same branch and automatically cancels older, in-progress runs when a new one is triggered.
* 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.
Enable Pyupgrade (`UP`) checks in Ruff, which drives the modernization of type hints.
This includes replacing `typing.Deque` with `collections.deque` and `typing.Tuple` with built-in `tuple` where applicable, improving consistency and adhering to modern Python conventions.
This change enables `F401` (unused import) checks in Ruff and configures per-file ignores for intentional top-level imports. The newly enforced check led to the removal of several unused imports across the codebase.
Additionally, the module existence check for `certifi` was modernized to use `importlib.util.find_spec` for a more efficient and robust approach.
* 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
Integrates the Ruff linter into the CI workflow alongside Black. This enhances code quality and consistency by catching common issues. Addresses an initial `F821` (undefined name) finding in `__init__.py` identified by Ruff, ensuring explicit module referencing.
Replaces numerous specific ignore entries (e.g., `.idea`, `.vscode`, `.cache`, editor backups) with a blanket rule to ignore all hidden root-level directories (`.*/`). Necessary exceptions like `.github/` and `.tx/` are explicitly un-ignored. This approach simplifies maintenance and prevents accidental commits of new tool-generated files.
Refactor RSS feed processing logic to enhance clarity and ensure correct precedence for resolved options. Renames functions and variables for better understanding, and inlines feed configuration logic. Adds new tests to verify how category, post-processing, script, and priority settings are applied hierarchically. Also provides a default display for empty RSS log categories.
* Simplify postproc queue storage and resolve serialization issues
* Revert save in end_job
* Not copying anymore, lock prevents history_queue from changing and the rest just reads nzo properties
* Keep compatibility with previous version files and load from absolute paths
* Calculate path once
* Expect relative to download_dir preferred
The `socket.getaddrinfo` function cannot directly process IPv6 literal addresses like `[::]` when they include brackets. Stripping these brackets ensures that host resolution and fallback logic correctly identify and use the specified IPv6 bind addresses, preventing lookup failures.
Closes#3404
* Replace duplicate nzo_ids in history database and use uuid4
* Remove SABnzbd_nzo on reuse
* Keep SABnzbd_nzo_ prefix for future jobs
* Try loading from multiple normal and future paths
* Purege NZO_FILE
* Rename NZO_FILE
* Allow failed migration to rollback
create_all_dirs checks if a directory exists before creating it, but
this can still fail with FileExistsError if another thread creates it
in between, or if the filesystem returns stale information. The error
gets caught by the generic OSError handler and logged as a failure,
even though the directory is actually there and everything is fine.
Handle FileExistsError separately so that existing directories are
silently accepted instead of being treated as errors.
* Fix PostProcessor handling of empty queues
Consolidate the logic for clearing the `work_available` signal and continuing the loop when no jobs are present. This removes a redundant initial check and centralizes the empty queue handling within the `queue.Empty` exception block, ensuring consistent behavior when no work is available.
* Fix PostProcessor's empty queue handling condition
The `handle_empty_queue` function is now only called when both the fast and slow job queues are explicitly empty. This prevents premature invocation when only one queue is exhausted, ensuring the end-of-queue state is correctly detected.
The `translations.yml` workflow commits generated updates to the repository. This change explicitly grants `contents: write` permission, removes the custom `AUTOMATION_GITHUB_TOKEN`, and streamlines redundant `git config` setup, relying on the default `GITHUB_TOKEN` for all repository modifications.
Explicitly define the minimum required permissions for various GitHub Actions workflows. This adheres to the principle of least privilege, enhancing security by limiting the scope of access granted to the GITHUB_TOKEN.
Further reduces the risk of immediately adopting new dependency versions by allowing more time for potential issues or vulnerabilities to be discovered.
To mitigate supply-chain attack risks, this changes the Transifex CLI installation method. Instead of executing a shell script from the `master` branch, a specific version (v1.6.17) is now downloaded directly as a pre-built binary from GitHub releases. This ensures a consistent, verified tool version is used in a workflow that commits directly to the repository.
Remove reliance on an external GitHub Action by using standard `git` commands for committing and pushing translation updates. This aligns with the strategy of minimizing third-party dependencies in workflows.
Ensures that translations do not break HTML or JavaScript rendering by removing newlines and carriage returns before the strings are cached and returned.
Closes#3375
Broke tests on Debian/Ubuntu, they reported it, never figured it out.
(#2274)
On Gentoo we skipped the failing test for years but 'just plain fails'
didn't sit right with me. We found the tests only fail using release
tarball, not git.
package.py script 'fixes' the line endings on .txt extensions but doesn't
account for a stillrarbutnotagoodname.txt rar binary in the test data.
This breaks tests on anyone using the release tarballs. So we skip mangling
the test data to allow for downstream CI to work.
* Perform diskspace check on complete directory for nzo
* Always check complete_dir even if complete_free is 0
* Slots require 3.10
* Fix direct unpack calculation
* Schedule resume against download_dir, complete_dir, or an arbitrary path
* Document params
* Replace Diskspace with returning a tuple
* Fix the broken things
* Add diskspace tests
* Execute file_done actions even if assemble failed
* Fix for tests since they call Assembler.assemble directly
* Attempt final steps even if assemble raises a non-IOError exception
* Do not add sockets that are not already connected
* Don't preemptively mark thread busy
* Clear nntp instance on failed connect
* Just use reset_nw like everywhere else
* Track when the socket is connected and idle connections can handle requested when connected (completed auth) or socket_connected
* Add tests for connection state handling
* Windows is really slow at this
* Rename connected to ready and socket_connected to connected
* Add database indexes
* Remove completed bytes index
* Allow duplicate query to short circuit
* Remove duplicate indexes
* Remove most of the query changes
* Fix commands which fail to be sent are lost
* Force macOS to use the select implementation
* Do not recreate lock when reinitialised
* Suppress errors when closing socket to ensure socket is closed
* Make connection errors on read or write both only wait 5 seconds before reconnecting
* Fix selector selection
* Only check generation under lock
* Use PollSelector
* Adjust monitored socket events as required to prevent hot looping
* Prevent write hot looping
* Guard against pending recursive call
* Already have EVENT_READ and don't need to handle it in two places
* Add a deadline for flushing cache contents on shutdown and don't throttle
* Revert "Add a deadline for flushing cache contents on shutdown and don't throttle"
This reverts commit e405b4c4f4.
* Always flush the whole cache but don't sleep when shutting down
* Implement direct write
* Support direct_write changes at runtime
* Check sparse support when download_dir changes
* Fixes to reverting to append mode and add tests
* Single write path, remove truncate, improve tests, add test for append mode with out of order direct writes
* assert expected nzf.assembler_next_index
* bytes_written_sequentially assertions
* Slim tests and mock load_article as a dictionary
* More robust bytes_written_sequentially
* Worked but guard Python -1 semantics
* os.path.getsize silly
* Add test with force followed by append to gaps
* Split flush_cache into its own function so the loop does not need to clear the article variable
* Fewer private functions
* Extract article cache limit for waiting constant
* Move option back to specials
* Use Status.DELETED for clarity
* Use nzo.lock in articlecache
* Document why assembler_next_index increments
* Remove duplicated code from write
* load_data formatting
* Create files with the same permissions as with open(...)
* Options are callable
* Fix crash if direct writing from cache but has been deleted
* Fix crash in next_index check via article cache
* Fix assembler waiting for register_article and cache waiting for assembler to write
* Simplify flush_cache loop and only log once per second
* Document why we would leave the assembler when forced at the first not tried article
* When skippedwe can't increment the next_index
* Rename bytes_written_sequentially to sequential_offset improve comments and logic
* Don't need to check when the config changes, due to the runtime changes any failure during assembly will disable it
* Remove unused constant
* Improve append triggering based on contiguous bytes ready to write to file and add a trigger to direct write
* Throttle downloader threads when direct writing out of order
* Clear ready_bytes when removed from queue
* Rework check_assembler_levels sleeping to have a deadline, be based on if the assembler actual pending bytes, and if delaying could have any impact
* Always write first articles if filenames are checked
* Rename force to allow_non_contiguous so it is clearer what it means
* Article is required
* Tweak delay triggers
* Fix for possible dictionary changed size during iteration
* postproc only gets the nzo
* Rename constants and remove redundant calculation
* For safety just key by nzf_id
* Not redundant because capped at 500M
* Tweak a little more
* Only delay if assembler is busy
* Remove unused constant and rename the remaining one
* Calculate if direct write is allowed when cache limit changes
* Allow direct writes to bypass trigger
* Avoid race to requeue
* Breakup the queuing logic so its understandable
* Make behaviour after reset more robust
* Remove use of hasattr and rename to generation
* I had a feeling this would be a circular reference
* Reset and increment generation under lock
* Pipelining and performance optimisations
* Refactor to remove handle_remainder and add on_response callback to allow inspecting of nntp messages
* Logic fix if there are sockets but nothing to read/write
* Fix logic errors for failed article requests
* Fix logic for reconfiguring servers
* Add guard_restart callback to pipelining_requests
* Fix article download stats
* Fix current article request shown via api
* Removal of DecodingStatus
* Fix circular reference
* Cleanup imports
* Handle reset_nw and hard_reset for inflight requests
* Improve __request_article behaviour using discard helper
* Article should be None here (before auth) but just in case
* Remove command_queue_condition unnecessary with the pull rather than push queue system
* During reset discard any data received prior to sending quit request
* Circular references again
* Revert to using bytearray
* Revert "During reset discard any data received prior to sending quit request"
This reverts commit ed522e3e80.
* Simpler interaction with sabctools
* Temporarily use the sabctools streaming decoder branch
* Fix most uu tests
* Reduce maximum pipelining requests
* Fix the squiggly line
* Remove some LOG_ALL debug code
* Make get_articles return consistent (None) - it now populates the server deque
* Reduce NNTP_BUFFER_SIZE
* Rename PIPELINING_REQUESTS to DEF_PIPELINING_REQUESTS
* A little refactoring
* Reduce default pipelining until it is dynamic
* Use BoundedSemaphore and fix the unacquired release
* Use crc from sabctools for uu and make filename logic consistent wit yenc
* Use sabctools 9.0.0
* Fix Check Before Download
* Move lock to NzbFile
* Use sabctools 9.1.0
* Minor change
* Fix 430 on check before download
* Update sabnews to work reliably with pipelining
* Minor tidy up
* Why does only Linux complain about this
* Leave this as it was
* Remove unused import
* Compare enum by identity
* Remove command_queue and just prepare a single request
Check if it should be sent and discard when paused
* Kick-start idle connections
* Modify events sockets are monitored for
* increased buffer, mesaurement time, changed file management and calcucation of result
* Write smaller chunks first, abort if time exceeds
* Move urandom dump to diskspeedmeasure, reduced buffer size to 16MB and recycled buffer for more efficient resource usage during writes
* fixed formatting issues
* fixed formatting issues
* fixed formatting issues
---------
Co-authored-by: L-Cie <lcie@sturmklinge.ch>
* Update all dependencies
* Pin tavern due to failure in newer versions
* User SABnzbd User-agent in wiki test
---------
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
Co-authored-by: Safihre <safihre@sabnzbd.org>
* Update all dependencies
* use socks5 server as test server
* make black happy
* improved active_socks5_proxy(): default port = 1080
* improved local_ipv4()
* use int_conv
* black
* use socks.socksocket.default_proxy directly
* active_socks5_proxy cleaner with int_conv
* correct to windows-2022
* socks.socksocket.default_proxy as check
* uniform naming socks5host/port
Closes#3154
---------
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
Co-authored-by: sanderjo <sander.jonkers+github@github.com>
Closes#1574
Add tests for long paths
Make sure long path is >260
Add rar test file with invalid Windows filenames
Add rar_unpack tests for unicode and passworded sets
Simplify Unrar command building
Add test for rar_invalid_windows
Remove check for 260 chars in rar_unpack
Should never happen anymore
Let Unrar rename invalid filenames
Check full path output if rar_unpack
Add helper for check
Correct test_rar_unpack_invalid_windows_filenames
Apply changes also to Direct Unpacker
Extend testing to make sure full paths are tested
Add tests for long paths inside rar
Unrar auto-rename message is different on Linux
* refactor outgoing interface
* refactor
* rollback old change
* We actually don't need another port
Closes#3153
* refactor
* refactor
* refactor to be compatible with old python versions
* forgot to remove match
* fix no route to host on mac
* fix no route to host on mac + rename interface to ip
* fix black + try to fix windows error
* fix black + try to fix windows error
* fix windows error
* fix windows failure
* rollback optional changes
* Remove optional type
* rollback changes + fix issue
* black change
* refactor
* missing refactor
Keep zip structure
Download all signed artifacts for release step
Correctly download all releases
Only sign when tagging release
Restore CI tests
Test production certificate
Closes#2870
* chore(deps): update all dependencies
* List Python 3.8 version of portend
---------
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
Co-authored-by: Safihre <safihre@sabnzbd.org>
* Include byte unit in quota strings
Fixes#2590
I expect to continue to iterate on some of the ideas in the comments
thereon, but this fixes the proximate issue mentioned in the issue.
This includes changes to the interface to properly interpret the new
strings:
- Remove the UI-based `B` designations as they are now tagged with
units from the api
- Let parseInt do its magic with string-y numbers plus units
- Expand parseInt for use in the checking whether quota is set
The display will be better in this `Glitter` case. This may well be
considered a breaking change for the API and not applied.
* Reduce computation slightly
No need to iterate over the evenly spaced unit sizes.
We can determine its magnitude quickly and convert it
into an index for our tags.
Avoiding the repeated divisons might also reduce error, but it is
unlikely to be noticeable.
* Drop trailing space when no units
The issue didn't expressly complain, but there is a trailing space when
all of the other unit information is empty. Might as well not include
it when it clearly will happen.
The use of `f-strings` might also simplify future maintenance.
* Better document to_units methodology
This addresses some code review concerns with respect to readability.
Frankly, having this much exposition in the comments might imply that
it's a lot less obvious than I thought at initial writing.
This also maps everything under `1024` directly to `0`. This avoids
concerns about potentially generating negative indices into the tags
tuple which would be surprising and wildly incorrect.
* bump par2cmdline-turbo to 1.2.0 for osx, and 1.2.0-utf8-20250212 for win
* Try UNC paths for par2cmdline-turbo update
---------
Co-authored-by: Safihre <safihre@sabnzbd.org>
* Add check XFF headers for remote ip in cookie
If verify_xff_header() then also check for the client IP in the XFF headers to ensure the IP used for the session cookie is actually the client IP and not a proxy IP.
* Fix code formatting
* Remove duplicate check for empty xff_ips. for -> for else
The URLGrabber sets Accept-encoding: gzip on requests, so a server may
respond with gzipped compressed data. That data is tested without
having been decompressed which then can result in unnecessary errors.
* Better analysis & better user info if newsserver connection fails
* make Black happy
* make Black happy
* make Black happy
* make Black happy ... corrected
* make Black happy ... corrected
* make Black happy ... corrected
* make Black happy ... corrected
* Safihre's feedback handled
* more Safihre's feedback handled
---------
Co-authored-by: sanderjo <sander.jonkers+github@github.com>
Turns out that there are NZBs that contain duplicate article-ID's within 1 file. This causes all "article in nzf.article" comparisons to return the wrong comparison.
* deobfuscate_subtitles
* deobfuscate_subtitles: unit test aka pytest
* deobfuscate_subtitles: unit test aka pytest
* deobfuscate_subtitles: no reanem is first part of filename is the samen
* deobfuscate_subtitles: no reanem is first part of filename is the samen
* deobfuscate_subtitles: no reanem is first part of filename is the samen
* deobfuscate_subtitles: more structured unit test method
* deobfuscate_subtitles: back to basic testing method
* deobfuscate_subtitles: cleanup
* deobfuscate_subtitles: cleanup
* deobfuscate_filenames.test_first_file_is_much_bigger() improved
* deobfuscate_subtitles(): checks on biggest file and srt files. input can be directory or filelist.
* rename to clearly_one_biggest_file()
* WIP on develop
* accept work by safihre
* do nothing when not one_file_is_biggest
* a lot of cleanup, also with help of the walrus
* a lot of cleanup, also with help of the walrus
* fix typo's in test_deobfuscate_filenames.py
* Update sabnzbd/postproc.py
Co-authored-by: Safihre <safihre@sabnzbd.org>
* handle review comments
* handle review comments
* remove import glob
* remove special underscore support. Add srt deob info into GUI-history
---------
Co-authored-by: sander <san.d.erjonkers+github@gmail.com>
Co-authored-by: Safihre <safihre@sabnzbd.org>
* fix when no connection (for example IPv6-test on IPv4-only connection)
* fix when no connection (for example IPv6-test on IPv4-only connection)
* make black happy ... hopefully
* make black happy ... hopefully ... linelength 120
* Added tests cases to wrap calls to the Apprise integration
* workaround to default config getting lost from test_misc.py
* 100% test coverage in send_apprise()
* Handle error code 451.
This is used by some servers to show that an article was intentionally removed.
Fix#2807
* Add a warning when an unknown status code is given for an article.
* Make warning message translatable.
* ipv6_staging: for ipv6 related stuff that is (allegedly) not yet mainstream
* ipv6_staging: separate internetspeed() ipv4 resp ipv6
* ipv6_staging: separate internetspeed() ipv4 resp ipv6
* ipv6_staging: separate internetspeed() ipv4 resp ipv6
* Move logic to internetspeed
* Add back alternative IPv6-address mapping
This reverts commit ec71d20d37.
* Usenetfarm added IPv6
---------
Co-authored-by: sander <san.d.erjonkers+github@gmail.com>
Co-authored-by: Safihre <safihre@sabnzbd.org>
* Make UI theme selection a non-advanced setting
* Call stylesheet a "theme" instead of a "skin"
---------
Co-authored-by: sbalbrecht <stpehen.b.albrecht@gmail.com>
It was relevant in Python 2.7-days.
This was we also don't make any external HTTP calls on start-up anymore, so hopefully we upset less virus scanners.
* happyeyeballs(): you can specify the family
* happyeyeballs(): you can specify the family
* happyeyeballs(): pytest
* happyeyeballs(): measure internetspeed_ipv4 and internetspeed_ipv6
* happyeyeballs(): measure internetspeed_ipv4 and internetspeed_ipv6
* happyeyeballs(): corrected pytest in case no ipv6 in environment
* internetspeed ipv4 and ipv6
* take care when ipv6 is not working
* take care when ipv6 is not working
* take care when ipv6 is not working
* take care when ipv6 is not working
* take care when ipv6 is not working
* black formatting
* faster test-HE on ipv4-only network
* comment in unittest
* requests in requirements.txt
* use urllib, not requests
* use urllib, not requests
* logging: tell family, if specified
* logging: tell family, if specified
* Merge remote-tracking branch 'origin/ipv6_HE_speedtest_address' into ipv6_HE_speedtest_address
* Merge remote-tracking branch 'origin/ipv6_HE_speedtest_address' into ipv6_HE_speedtest_address
* cleanup of getipaddress
* cleanup of getipaddress
* cleanup of getipaddress
* cleanup of getipaddress
* Merge remote-tracking branch 'origin/ipv6_HE_speedtest_address' into ipv6_HE_speedtest_address
* Changes to PR
* Make sure the returned IP is valid
---------
Co-authored-by: sander <san.d.erjonkers+github@gmail.com>
Co-authored-by: Safihre <safihre@sabnzbd.org>
Reduced time between connection attempts to prevent slow hosts that happened to be the first in the list to win from faster second-in-list.
Add test for our IPv6 mapping
* Refactor the way we getaddrinfo and use Happy Eyeballs
* Move tests to right directory
* Do not run Happy Eyeballs for only 1 address
* Process feedback
* Make sure we always have a canonname
* Show IP and resolved name in Status Window
* Simplify Status server updates
* Remove unused imports
Correct restart on macOS binary.
Allow to be less strict about file removal.
Remove not needed zip parameter.
Remove old modifications of sys.argv.
Make sure that after restart we still log to console.
* Add par2cmdline as option for windows, still default to multipar.
* Fix tests and do not give par2cmdline long-paths on Windows
* Set enable_multipar to true
---------
Co-authored-by: Safihre <safihre@sabnzbd.org>
* feat: add dark mode for wizard, config, and login
* combine the dark skins
* make the buttons the same as in Glitter
* load the night theme based on config setting
* Changes to darkmode
---------
Co-authored-by: Safihre <safihre@sabnzbd.org>
* Add multi-select to history
* Fix checkbox state when multi-selecting on queue and history
* Refactor multi-select feat and fix for tabbed layout
* Fix failing ci tests
* Fixes and improvements
* Basic direct write implementation
* Correctly track file_position and only write continuous
* Direct write with sparse files
---------
Co-authored-by: Safihre <safihre@sabnzbd.org>
* Deobfuscate ON by default
* Correct data test set: filename that is not obfuscated. Except test_par2file
* Correct data test set: filename that is not obfuscated. Except test_par2file
* Commented out test in test_par2file.py
* Commented out test in test_par2file.py
* assert for unicode_rar 我喜欢编程 now working too
---------
Co-authored-by: sander <san.d.erjonkers+github@gmail.com>
* 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>
* Decode articles as they are downloaded
* Combine the recv and process methods
* Less cryptic futures
* Lock get_article because it can be called by multiple threads within the pool
* Add handle_process_nw_result
* Use add_socket helper
* Lock finish_connect_nw
* Add locks and remove callback
* Use same lock for updating nzo statistics
* Remove None typing
* Add downloader lock
* read_fds by index because it will never fail
* Use downloader lock
* Translate ascii control chars below value 32
* Try to make code and tests consistent
* More test fixing
* Delete too much
* Different approach
* Finally got it?
* Start from 0
* Convert \0 to _ for all systems
* Check if CH_ILLEGAL_WIN is translated to CH_LEGAL_WIN
* Test specific chars
* Improve dirscanner performance and reduce system calls
* Break up one liners
* Rename functions and add typings
* yield from instead of looping
* Fix optional typing
* Replace threads with asyncio
* Use full module path
* Replace list comprehension with for loop
* Give other coroutines a chance to run if we ignore a path
* Remove uncesserary unnecessary asyncio.sleep on skipped path
* Catch and report all exceptions within the scanner task to the user to ensure the overall scanner task cannot crash
* Log traceback
* Threaded polling of connections
* Do speed limit check after handling
* Use ThreadPoolExecutor, remove code for updating recv_threads while running
* Get newswrapper inside try
* Change default settings to 2 threads
---------
Co-authored-by: Safihre <safihre@sabnzbd.org>
* include https config files in backup
* add constants for default https config filenames
* refresh test_config, add coverage for https backup
* remove some unicode from the tests
* On Windows we use long-paths
---------
Co-authored-by: Safihre <safihre@sabnzbd.org>
* Gradual slowdown on filling queues
* Move delayed counters to new slowdown check, otherwise they will rarely trigger
* Simplify the full decoder part a bit
* Reduce sleep aggressiveness a bit
* Make a constant for the queue level slowdown limit
* Rename the slowdown limit variable and put it in constants with the other queue limit variables
* Also constants...
* Make black happy
* Write first article directly
* Add first article to assembler in usual place instead of ArticleCache
* Remove redundant deref
* Update comment to reflect new code
* Partly restore old code
* First article should not always be added to the queue if SAB has started downloading the other parts
* Yet another redundant deref :(
* Make downloader use used buffer size to determine if it's ok to sleep
* Log number of times slept and average time slept last 10 seconds
* Log if downloader slept much too long
* Improvements to sleep debugging
* Remove get_stable_speed
* Stop using 0 as failed and use new crc32 value in SFV check
* Make nzf.crc32sum differentiate between uninitialized, valid and invalid CRC32 value
* Replace crc32sum with assembled and use crc32 value instead
* Only set on_disk and don't set decoded until article is saved to cache (#2403)
* Mark unavailable articles as saved
* Save broken article if a valid one doesn't exist
* Change bad article message a bit
* Reduce to only set on_disk and don't set decoded until article is saved to cache
* Use CRC32 from PAR2 instead of MD5
* Move crc32calc.py to utils
* Update credits in crc32.py, use crc32 in test_par2file.py
* Various smaller changes to CRC32 patch
* Handle unfinished par2 files better
* Optimized crc32 calculations
* Rename md5sum to crc32sum and include filesize check
* Mark unavailable articles as saved
* Save broken article if a valid one doesn't exist
* Change bad article message a bit
* Reduce to only set on_disk and don't set decoded until article is saved to cache
* better logging with login from multiple IP
* warning in one line
* warning in one line
* warning in one line
* cleanup
* errormsg in better place
* Patch error
Co-authored-by: sander <san.d.erjonkers+github@gmail.com>
Co-authored-by: Safihre <safihre@sabnzbd.org>
* Limited refactoring
* Remove explicit setblocking from servertests.py
* Make combine_chunk exactly 5 bytes so we can use ==
* Move timeout down a bit
* Trying to find cause of git bug #2345
* Try to find IP using happyeyeballs first, fall back to default if it fails
* Fix mistake
* Add host name to connection error message
* Always debug log IP address
* Do a more thorough check when a bad try_list is detected
* Improve idle job check and fix DNS lookup problem
* Loop through copy of article list and move nzf.reset_try_list below the article check
Closes#2320
This way the environment variable SAB_PASSWORD (whose documentation
says is supplied by user OR the nzb) is filled properly and the
password is available in a preprocessing script.
* detect fully encrypted rars
* debug.warning working, nzo.fail_msg alas is overwritten
* a bit of clean-up
* a bit of clean-up
* the real clean-up
* no intermediate variable
Co-authored-by: Safihre <safihre@sabnzbd.org>
* Shorter message
Co-authored-by: Safihre <safihre@sabnzbd.org>
* more clean-up
* unittest
Co-authored-by: sander <san.d.erjonkers+github@gmail.com>
Co-authored-by: Safihre <safihre@sabnzbd.org>
* Update setuptools from 63.4.2 to 65.0.0
* Update orjson from 3.7.11 to 3.7.12
* Update jaraco.text from 3.8.1 to 3.9.0
* Update more-itertools from 8.13.0 to 8.14.0
* Update pytz from 2022.1 to 2022.2.1
Co-authored-by: pyup-bot <github-bot@pyup.io>
* Check if host is valid: an IP address, or a name/FQDN that resolves
* Check if host is valid: an IP address, or a name/FQDN that resolves
* default to "127.0.0.1"
* default to "127.0.0.1"
* manual black
* manual black
* manual black
* based on feedback, plus back-to-basics
* based on feedback, plus back-to-basics, plus debug logging
* based on feedback, plus back-to-basics, plus debug logging
* based on feedback, plus back-to-basics, plus debug logging
* clean formatting
* clean formatting
Co-authored-by: sander <san.d.erjonkers+github@gmail.com>
* Update pyinstaller from 5.2 to 5.3
* Update setuptools from 63.2.0 to 63.3.0
* Update orjson from 3.7.8 to 3.7.11
Co-authored-by: pyup-bot <github-bot@pyup.io>
* Comment block that explains what deobfuscation does
* get better logging (with reason of no deobfuscation), leading to other code structure
* get better logging (with reason of no deobfuscation), leading to other code structure
* get better logging (with reason of no deobfuscation), leading to other code structure
* based on feedback: comment with typical cases to the beginning of function, error logging if file is not given/found, other logical notation in if-statement
* Update setuptools from 63.1.0 to 63.2.0
* Update cherrypy from 18.7.0 to 18.8.0
* Update jaraco.functools from 3.5.0 to 3.5.1
* Update jaraco.collections from 3.5.1 to 3.5.2
* Update jaraco.text from 3.8.0 to 3.8.1
* Update jaraco.classes from 3.2.1 to 3.2.2
* Update jaraco.context from 4.1.1 to 4.1.2
* Update tempora from 5.0.1 to 5.0.2
* Only pick biggest file for deobfuscation
* unit tests working again
* unit tests working again
* get counter nr_files_renamed right
* also deobfuscate sample and other files with same basename
* also deobfuscate sample and other files with same basename
* naming, comments
* unit test with just one small file (should get deobfuscated). Plus improved text/names.
* Moved most typical unit test (test_deobfuscate_big_file_small_accompanying_files() ) more to the top
* Moved most typical unit test (test_deobfuscate_big_file_small_accompanying_files() ) more to the top
* Update cryptography from 37.0.3 to 37.0.4
* Update cryptography from 37.0.3 to 37.0.4
* Update pyinstaller from 5.1 to 5.2
* Update pyinstaller-hooks-contrib from 2022.7 to 2022.8
* Update orjson from 3.7.6 to 3.7.7
* Update cherrypy from 18.6.1 to 18.7.0
* Update cryptography from 37.0.2 to 37.0.3
* Update cryptography from 37.0.2 to 37.0.3
* Update orjson from 3.7.2 to 3.7.3
* Update chardet from 4.0.0 to 5.0.0
* Force selenium<4.3.0
Co-authored-by: pyup-bot <github-bot@pyup.io>
* Update pyinstaller-hooks-contrib from 2022.6 to 2022.7
* Update setuptools from 62.3.2 to 62.4.0
* Update pkginfo from 1.8.2 to 1.8.3
* Update orjson from 3.7.1 to 3.7.2
* Update pyinstaller from 5.0.1 to 5.1
* Update pyinstaller-hooks-contrib from 2022.4 to 2022.5
* Update setuptools from 62.2.0 to 62.3.2
* Update sabyenc3 from 5.3.0 to 5.4.0
* Update feedparser from 6.0.8 to 6.0.10
* Update ujson from 5.2.0 to 5.3.0
* Update sabyenc3 to 5.4.1
Co-authored-by: pyup-bot <github-bot@pyup.io>
* functions to test directory for writing capabilities
* functions to test directory for writing capabilities
* use checking in postproc, and give warning if needed
* use checking in postproc, and give warning if needed
* put into function, with translatable folder names
* remove test file if still there
* better message formatting
* remove friendly directory name. Less comments
* move stuff into filesystem.py
* clean it up
* unit test for check_directory_writing_capability on tempdir
* unit test for check_directory_writing_capability on tempdir
* unit test for check_directory_writing_capability on tempdir
* unit test for check_directory_writing_capability on tempdir
* unit test for check_directory_writing_capability on tempdir
* Update sabnzbd/filesystem.py
Co-authored-by: Safihre <safihre@sabnzbd.org>
* feedback processed
* feedback processed
* feedback processed
* Merge remote-tracking branch 'origin/check_filesystem_capabilty' into check_filesystem_capabilty
# Conflicts:
# sabnzbd/filesystem.py
* typo: uniformed on "writable"
Co-authored-by: Safihre <safihre@sabnzbd.org>
* Update cryptography from 36.0.2 to 37.0.1
* Update cryptography from 36.0.2 to 37.0.1
* Update wrapt from 1.14.0 to 1.14.1
* Update pywin32 from 303 to 304
Co-authored-by: pyup-bot <github-bot@pyup.io>
We only care about missing/broken articles in files that we have par2 for. So we check for each NZF if it has bad articles, and only fail if it is part of a par2 set. Additionally we check if the file size matches the one from par2.
Since this also enables CRC check for sabyenc3, it will be slower and the default of num_simd_decoders is increased to 2.
* Update pyinstaller-hooks-contrib from 2022.2 to 2022.3
* Update setuptools from 60.10.0 to 62.0.0
* Update cheetah3 from 3.2.6.post1 to 3.2.6.post2
* Stop Cheetah3 updates
Co-authored-by: Safihre <safihre@sabnzbd.org>
* checkdir: is_writable(check_dir: str) -> bool
* user can define well known extensions
* user can define well known extensions
* user can define well known extensions
* user can define well known extensions
* user can define well known extensions
* user can define well known extensions
* user can define well known extensions
* unit-test
* unit-test
* unit-test
* based on feedback
* introduce validation=lower_case_extensions_without_dot to get clean extensions
* introduce validation=lower_case_extensions_without_dot to get clean extensions
* introduce validation=lower_case_extensions_without_dot to get clean extensions
* logging.debug of all performance measurements
* logging.debug of all performance measurements
* logging.debug of all performance measurements
* logging.debug of all performance measurements
* black black black
* internetspeed ... logging.debug start & done
* internetspeed ... back to total 8 seconds, plus a Note in comments
* no more logging "starting ..."
* change the Note a bit
* internetspeed: correct seconds, and Note
* SAB-standard wording. Plus meausurement of duration, where possibly relevant
* SAB-standard wording. Plus meausurement of duration, where possibly relevant
* shorter variable name for disk writing MB per sec
* shorter variable name for disk writing MB per sec
* Use attribute poster of file element, if attribute subject ist missing
* Don't fail, if subject is missing.
* Textual change
Co-authored-by: Safihre <safihre@sabnzbd.org>
* Backup and restore admin data
* Don't import archives containing subpaths
* Show result after uploading
* Use existing upload system and fixed list of admin files
* Fix confusing order of code lines
* Add translations and link from wizard
* Refactoring, change some names and move some code to sabnzbd.config
* Remove unused imports
* Remove queue and scan databases from backup
* Style changes
* Code changes
* Add tests and don't crash if any admin files are missing
* Cleanup
* Small changes and rebase on develop
Co-authored-by: Safihre <safihre@sabnzbd.org>
* Do not deobfuscate/rename anything if there is a typical DVD or Bluray directory
* Do not deobfuscate/rename anything if there is a typical DVD or Bluray directory
* Do not deobfuscate/rename anything if there is a typical DVD or Bluray directory
* Do not deobfuscate/rename anything if there is a typical DVD or Bluray directory
* Do not deobfuscate/rename anything if there is a typical DVD or Bluray directory
* detect DVD/Bluray structure, and do not run deobfuscate on that
* detect DVD/Bluray structure, and do not run deobfuscate on that
* detect DVD/Bluray structure, and do not run deobfuscate on that
* detect DVD/Bluray structure, and do not run deobfuscate on that
* detect IGNORED_MOVIE_FOLDERS in filelist
* detect IGNORED_MOVIE_FOLDERS in filelist
* better code
* better code
* better code
* better code
* better code
* use one-liner
* wording in comment
* unittest for VIDEO_TS
* unittest for VIDEO_TS
* Do not apply permissions if not requested by the user, but remove xbits
* Verify umask and user-permissions and warn for potential access problems
* Correctly name umask/permissions options
* Apply permissions only on download_dir creation
* Refactor some permissions related actions
* Block setting permissions=0 and only stat when no custom_permissions
* coding style for 7z unpacking
* coding style: better order
* make black happy
* make black happy
* make black happy
* make black happy
* make black happy
* make black happy
* use two standard message so no translations needed
* use two standard message so no translations needed
* setname_from_path(sevenset)
* setname_from_path(sevenset)
* anything ret > 0 is one case
* if too little disk space reported by 7z unzipping, report so in GUI
* comment about 7z version needed
* find and print 7z version at startup
* feedback from safihre
* change to existing wording, so no translations needed
* change to existing wording, so no translations needed
* even better wording: re-use existing error message
* Rework adding of NZB's to use filehandlers
* Use zf.open() instead of zf.read()
* Make SevenZip-class compatible with file handler approach
* Do not attempt to overwrite existing admin-NZB
* Reset pointer when checking for incomplete NZB
* No longer check for incomplete NZB
* Refactor of archived NZB handling
* Read XML from file using iterparse
* Ignore XML namespace
* Minor cleanup
* More tweaking
* Small improvements to the NZB-backup process
* Add type-hint and logging of backup
* Don't remove nzo data after failed import
Co-authored-by: Safihre <safihre@sabnzbd.org>
* Add option to preserve Downloader run state
* Add updating to set_paused_state
* Restore set_paused_state call
* Messed up again
* Requested changes
* Missed one
* Add testable socks support
* Messed up merge
* Use proxy for urllib.request.urlopen
* Reset socket before trying to get public IP
* Add socks requirement
* PySocks, not socks?
* Use only PySocks
* Clean up and reduce number of new translations
* Move configuration to special variable socks5_proxy_url
* Remove useless dereferencing
* Catch OSError on proxy preconnect
* Try only setting socks proxy once
* Missed some spots
* Catch all errors for IPv6 checks
* Move proxy initialization up before threads are started
* No special `sock.connect` required for Socks5
* Revert "No special `sock.connect` required for Socks5"
This reverts commit 5e901f8b58.
* Remove callback and ORIGINAL_SOCKET variable
* Move all `sock.connect` code
* Create SSLContext only once for each server
It is re-created if server-settings are updated.
* Add SOCKS5 proxy configuration to General page
* Show if proxy is active in Status-window
Co-authored-by: Safihre <safihre@sabnzbd.org>
Before 3.4.0, only for TV sorting we allowed to set 0 categories. But for Movies and Date Sorting we did require at least 1 category to be set. This was harmonized in 3.4.0, breaking existing setups. Added warning for those users.
The Sorting behavior is different from Notifications: in Notifications selecting Default only(!) means to apply it to all categories.
However, that has never been the case for Sorting. So for now added a bit more help texts to the Affected categories box on both pages.
* Add required server option
* Use plan_resume() instead of the resume_task system
* Retry articles on required servers after connection failure
* Update comment to match new code
* Remove unnecessary try
* Implement regex to match the filename in the content-disposition header.
The following srings will match:
filename=Zombie.Land.Saga.Revenge.S02E12.480p.x264-mSD.nzb; filename*=UTF-8''Zombie.Land.Saga.Revenge.S02E12.480p.x264-mSD.nzb
filename=Zombie.Land.Saga.Revenge.S02E12.480p.x264-mSD.nzb;
filename*=UTF-8''Zombie.Land.Saga.Revenge.S02E12.480p.x264-mSD.nzb
* Missed quote
* Implement the mailbox/Message solution
* Add basic tests
* Add `attachment;`
* Add example with attachment.
* Fix some linting.
* Added edge case tests.
* Added comment.
* Added test to include path elements.
* Only try the content-disposition header when it has `filename` in it
* Project uses double quotes.
* Update test.
* Add `attachment;`
* black formatter
* remove release names.
* trailing commas
* quote enclosures
* Always deobfuscate names from par2
* Different par2 test
* Different par2 test take 2
* Make par2 filename decoding optional and add some typing
* Rename variable
* record new files generated based on par2
* record new files generated based on par2
* test first par2 based renaming, then deobfuscate obfuscated names
* remove commented-out line
* corrected contents zip-file
* try again, github
* try again, github
The side effect of this change is also that if you have an nzb-backup dir with the file already present that this second will be found duplicate, even before the first job has finished in the queue. Relates to #727
* Use guessit for sorting and sample detection
* Fix bad logic in is_sample
* address comments, pt. 1
* address comments pt. 2
* address comments, pt. 3
* don't reference title before assignment
* whoops... overlooked the lowercasing
* add another title safeguard
* prevent uninitialized use of variable
* fix for jobs that should not be sorted
* don't list excluded guessit props in the interface
* insert linebreak between guessit props under pattern key
* use constant for excluded props
* dump COUNTRY_REP
* block rebulk log spam
* remove redundant season default; don't set for episodes
* make substitution regex a raw str
* correct_extension: basics, including unittest
* correct_extension: basics, including unittest
* correct_extension: puremagic into requirements.txt
* correct_extension: introduce a main for testing from CLI
* correct_extension: parse all parameters on CLI as files
* correct_extension: parse all parameters on CLI as files
* correct_extension: CLI parameter "-p" for privacy output
* correct_extension: has_common_extension() and most_likely_extension()
* correct_extension: has_common_extension() and most_likely_extension()
* correct_extension: add extension if file has no commonly used extension
* correct_extension: Black happy ... hopefully
* correct_extension: Black happy ... hopefully
* correct_extension: process feedback, mainly the extenions lists ^H^H^H^ tuples
* correct_extension: process feedback, mainly the extenions lists ^H^H^H^ tuples
* correct_extension: process feedback, mainly the extenions lists ^H^H^H^ tuples
* correct_extension: process feedback, mainly the extenions lists ^H^H^H^ tuples
* correct_extension: cleaned up
* correct_extension: cleaned up ... github-black now happy?
* correct_extension: cleaned up ... github-black now happy?
* correct_extension: cleaned up ... github-black now happy?
* correct_extension: cleaned up ... github-black now happy?
* correct_extension: cleaned up ... github-black now happy?
* correct_extension: easier if-then-logic, check if new_extension_to_add is filled.
* correct_extension: if puremagic does recoging txt or nzb, check ourselves
* correct_extension: if puremagic does recoging txt or nzb, check ourselves
* correct_extension: only files!
* correct_extension: only files!
* correct_extension: rNN files not common extension, plus easier testing
* correct_extension: clean-up ... no more boolean extension_too
* correct_extension: requirements.txt, solved a TODO, and use get_ext()
* correct_extension: a comment added
* correct_extension: correct typing, correct txt and nzb extension
* correct_extension: extensions always with dots, bug fix in what_is_most_likely_extension()
* correct_extension: back on track?
* correct_extension: back on track?
* correct_extension: better comments
* Add article queue and change article tries system
* Don't reuse queued articles with get_articles
* Add article_queue to server slots
* Generalize get_articles
* Set fetch_limit to be at least 1
* A little tweaking
* More micro optimization
* Small tweaks
* Remove misplaced reset_article_queue()
* Call reset_article_queue() from plan_server
Co-authored-by: Safihre <safihre@sabnzbd.org>
* show CPU architecture in logging.info
* show CPU architecture in logging.info ... make black happy
* show CPU architecture in logging.info ... comment
* show CPU architecture in logging.info ... comment
* show CPU architecture in logging.info ... comment
* show CPU architecture in logging.info ... oneliner
* disk_free_macos_clib_statfs64() to report correct available disk space on MacOS
* disk_free_macos_clib_statfs64() ... correct call
* feedback processed into better code, and improved comments
* MACOSLIBC into __init__. And some comments about gnu libc
* import ctypes.util
* log ctypes.get_errno() in case of problems
* more cleanup and clarifications based on feedback
* mention python bug report in comment
* ... to trigger the CI again
* ... typo
* deobfuscate: rename accompanying (smaller) files with same basename
* deobfuscate: do not rename collections of same extension
* deobfuscate: collection ... much easier with one loop, thanks safihre.
* deobfuscate: globber_full, and cleanup
* deobfuscate: unittest test_deobfuscate_big_file_small_accompanying_files
* deobfuscate: unittest test_deobfuscate_collection_with_same_extension
* deobfuscate: unittest test_deobfuscate_collection_with_same_extension
* Don't do a full calculation for every call to BPSMeter.update()
* Log current bps in MB/s
* Use to_units
* Add an bps update after disconnect or shutdown
* Switch to force_full_update being default
* Force update if bandwidth limit is set
* Fixed the real problem
Co-authored-by: Safihre <safihre@sabnzbd.org>
* pre-create subdir it needed
* pre-create subdir it needed: check if already exists
* use os.makedirs() to handle subdir1/subdir2/blabla
* protect against malicous "..", and better naming
* check for Windows \ and POSIX /
* check again within path, typo and formatting
* regex: square brackets
* cleanup: only "/" can occur in par2
* cleanup: better logging
* unit test: testing of filesystem.renamer()
* if subdir specified in par2: let filesystem.renamer() do all the work
* if create_local_directories=True, then renamer() must stay within specified directory. Plus unittest for that.
* if create_local_directories=True, then renamer() must stay within specified directory. Plus unittest for that.
* more comments in code
* use filesystem.create_all_dirs(), less logging, clearer "..", and other feedback from Safihre
* make remote black happy too
* Small changes in wording of comments and error
Co-authored-by: Safihre <safihre@sabnzbd.org>
* Update uni_config bootstrap css to same version of js (3.3.7).
* small accessibility change, removed thin dot border on focus
* Ignore VS Code settings folder
* cherry picked 'Fix disabled select for Glitter Night'
* glitter night - fix search border color
* Add rtl on main page
* Adjustments to rtl
* Forgot to add black check for this checkout
* Remove unnecessary style
* Remove more redundant attributes
* Some more reordering and alignment
* Align sorting and nzb drop downs
* Update NZB details and shutdown page
* Fix format
* Fix SABnzbd Config title tag
* Change file list header direction
* Set rtl variables in build_header instead and test dir="rtl" in config pages
* Revert some changes and handle styling using CSS
* Move more items to CSS
* Config RTL
* Move even more to CSS
* Small tweak
Co-authored-by: Safihre <safihre@sabnzbd.org>
* add tests for adding nzbs
* restore clean_cache_dir fixture, unbreak utils tests
* include tests for partial and malformed nzbs
* test handling of prio from nzb metadata category
* update params of test_adding_nzbs_malformed
* add metadata to sabnews nzb creator
* also test with size_limit
* test prio with dupe detection
* remove leftover todo entry
* move pause and cleanup to fixture; rename functions
* verify input values for scripts
* update and parametrise test_api_queue_change_job_script
* fortify cfg with script validation, fix test
* add typing to is_valid_script function :)
* move list_scripts function to filesystem
* also move windows-specific pathext stuff
* First working version
* Remove pprint
* Black
* Use date type and move to 5 minute polling
* Give hints about intended usage in explain text
* Use scheduled tasks and some smaller changes
* Black
* Remove hidden fields from form
* Cleanup
* This is not the easiest part to get right
* Black hook take 3
* Rework the server check tasks
* Show quota left for server
* Move Server description
Co-authored-by: Safihre <safihre@sabnzbd.org>
Closes#1455
* Save all interface values if useGlobalOptions is true
* Try to fix the tests
* New test test
* Another test test
* Remove default value for interface_settings
* urlgrabber limit filename to avoid tracebacks
* urlgrabber limit filename to avoid tracebacks: black
* urlgrabber limit filename to avoid tracebacks: black
* filename_limit ... 2020-01-15
* filename_limit: into sanitize_filename()
* filename_limit: black and typo and logging
* filename_limit: debug show full filename
* filename_limit: unittests
* sanitize_filename(): take care of feedback: one ASCII method, handly silly extension lengths
* sanitize_filename(): tests/test_filesystem.py ... make black happy
* sanitize_filename(): typo in comment
* sanitize_filename(): test_filesystem.py ... black
* sanitize_filename(): more unittests, and DEF_FILE_MAX (yet without GUI option)
* sanitize_filename(): always use DEF_FILE_MAX
* sanitize_filename(): black
* sanitize_filename(): handle UTF8 correct (>1 byte). DEF_FILE_MAX = 255
* sanitize_filename: measure bytes (not chars), DEF_FILE_MAX = 255 - 6, no test-writing in unittests
* sanitize_filename: constants.py ... black
* sanitize_filename: comment about extension
* DEF_FILE_MAX = 255 - 10 again, to solve adding ".nzb.gz" elsewhere
This might cause problems, but it's worth a try. It seems we resetted the trylists so often, this would cause a lot of extra CPU cycles to try all articles again.
* SSDP: also log the User-Agent
* SSDP: also log the User-Agent
* SSDP: also log the User-Agent
* SSDP: ssdp_broadcast_interval in seconds, configurable via GUI -> Specials
* SSDP: ssdp_broadcast_interval as optional parater to the SSDP class
* SSDP: less is more: start_ssdp(*args, **kwargs):
* SSDP: less is more: start_ssdp(*args, **kwargs):
* SSDP: handle if no User-Agent specified
* SSDP: small change
Co-authored-by: Safihre <safihre@sabnzbd.org>
* Add pause on full Complete Download Folder and optional time limit for full disk pause
* Use nzo.bytes_tried in completed dir disk full check
* It's so black or white
* Don't pause on full download disk until it's necessary and don't apply timed pause to temporary disk
* Simpler ifs
* Compare with downloaded bytes, not remaining
* Fix comparison
* Increase pause check to 90% finished
* Subtract par2 files and increase limit to 95%
* Use checkbox for automatic resume and task scheduler for checking free space
* Make canceling resume task a separate method
* Black
* Replace some logging.debug with logging.info
* Remove sabnzbd.directunpacker.abort_all
* Rewrite explain-fulldisk_autoresume explanation
* Ignore complete_free if 0
* Style changes
* Remove scheduled task if the downloading is continued
* 'Every few minutes'
* Fix unchecking of fulldisk_autoresume in config page and don't do autoresume task if it has been disabled
* Black is rather picky
Co-authored-by: Safihre <safihre@sabnzbd.org>
https://forums.sabnzbd.org/viewtopic.php?f=3&p=123147
In SABnzbd 3.x we write incomplete files to the disk instead of waiting for a file to be 100% complete.
So the password check fails because it will check part001 and automatically continue to part002. Instead of crashing with a "can't find part002" (this we expect) it finds a incomplete part002 and crashes with a different error that we don't catch.
Alternatively it can crash due to starting to check on part002 while part001 isn't there yet. This used to work, but broke now.
* add select by nzo_id to history api
* add select by nzo_id to queue api
* add tests for selecting by nzo_ids
* Do not run codesign step on pull requests
Co-authored-by: Safihre <safihre@sabnzbd.org>
* Add option for unlimited width
* Add skintext
* Select multiple extra columns
* Fix some markup
* Suggested changes
* Retrigger tests
* Make it possible to select multiple history columns as well
* Do not show extra columns on <1200px
* Fix Add NZB-row
Co-authored-by: Safihre <safihre@sabnzbd.org>
* GUI show warning for enabling HTTPS
* GUI show warning for enabling HTTPS. Make black happy
* GUI show warning for enabling HTTPS: warning in separate string
* GUI show warning for enabling HTTPS: Warning embedded
* GUI show warning for enabling HTTPS: proper class stuff
* Show current server speed on server config page
* Show server bps on Status and interface page
* Make black happy
* Remove server bps from config page
* Small optimization tweak
Co-authored-by: Safihre <safihre@sabnzbd.org>
* Make sleep more fine grained and add short sleep when no processing is required
* Fix black complaint
* Only calculate sleep time when needed
* Remove empty line
* Add sleep_time variable to Downloader
* Make sure it sleeps in decoder and BPSMeter, even when sleep_time is 0
* Longer sleep for decoder and bandwidth limit delays
* Remove BPSMeter get_stable_speed as it is no longer used
* retrigger checks
* Updates based on feedback
* No more minimum value
* 0.01 it is
Co-authored-by: Safihre <safihre@sabnzbd.org>
* Only check idle servers for new articles twice per second
* Fix black complaint
* Store time.time() in variable in DL loop
* No need to check server for last_busy if it was just set
* diskspeed: follow pylint's advice, and more pytesting
* diskspeed: improved hint, catch relevant exceptions
* diskspeed: lower tun time to 0.5 s (as we run it twice)
* diskspeed: make black and pylint happier
* Delete somefile.txt
* Add base implementation of SSDP util
* SSDP+XML: working setup #1
* SSDP+XML: with socket ... as sock
* SSDP+XML: unique UUIDs
* SSDP+XML: simpler constructions of XML URL
* SSDP+XML: cleaner SSDP and XML, steady UUID in XML, better logging
* SSDP+XML: UUIDs into __init__(). Better, innit?
* SSDP+XML: Make black happy again
* SSDP+XML: Make black happy again ... now for interface.py
* SSDP+XML: creation of SSDP message and XML to __init__()
* SSDP+XML: changes based on feedback
* SSDP+XML: no more SABnzbd references in ssdp.py. No network is OK now.
* SSDP+XML: references to specs for SSDP and the XML
Co-authored-by: Safihre <safihre@sabnzbd.org>
* fix deprecation warning in sabnews regex
* enable text, xml returns from get_api_result
* add api tests
* add functional api tests
* add tavern.yaml files to test data
* explicitly add lxml to work around pip dependency issues
* prevent pytest from picking up the tavern files
* Revert "fix deprecation warning in sabnews regex"
This reverts commit 4f0b7131e7.
* address minor issues
* integrate fixtures into conftest
* black :/
* harden queue repair test
* try a workaround for extremely slow test runs on windoze
* Correct server detection in functional tests
* move scripts dir inside SAB_CACHE_DIR
* also relocate the generated script
Co-authored-by: Safihre <safihre@sabnzbd.org>
SMTP protocol dictates that all lines are supposed to be separated
with CRLF and not LF (even on LF-based systems). This change ensures
that even if the original byte string message is using `\n` for line
separators, the SMTP protocol will still work properly.
This resolves sabnzbd#1669
Fix code formatting
* randomize age for generated nzb files
Useful for testing queue sorting function of the api. Timestamp values are randomly chosen between september '93 and now.
* Sigh.
* only replace the first occurence of "script_"
Use of str.replace() without a count replaces all occurences. As a result, scripts with filenames such as "my_script_for_sab.py" would be mangled when trying to set them as action on queue completion.
* also modify the check of the action var
* deobfuscate: based on newfiles
* deobfuscate: based on newfiles, black-cleaned
* deobfuscate: yet another black try
* deobfuscate: with upgraded black module
* deobfuscate: improved unittests
* deobfuscate: improved unittests
* deobfuscate: improved unittests
* deobfuscate: removed deobfuscate_dir()
* deobfuscate: extra unittests: lite and nasty
* deobfuscate: black try again
* deobfuscate: black try again, and again
So we no longer see 110/100MB completed.
Articles could keep coming in after the par2 files were already postponed. When postponing the articles the bytes_tried are already decreased.
* Deobfuscate final files: more intelligence, default obfuscated = True, more unit testing
* Deobfuscate final files: typo's
* Deobfuscate final files: cleanup of is_probably_obfuscated
Turns out long-path notation makes os.path.abspath not trim the final \ of a path. It does remove it on Linux or on non-long-paths. So we just remove the long path during modification and add it back at the end.
Closes#1588.
* Deobfuscate / rename final files
* black formatted ...
* Deobfuscate / rename final files: unittests
* Deobfuscate / rename final files: unittests
* Deobfuscate / rename final files: unittests formatting
* Deobfuscate / rename final files: unittests of real renaming
* Deobfuscate / rename final files: unittests of real renaming - black formatting ...
* Deobfuscate / rename final files: unittests of real renaming - no subdir "data" as travis was complaining
* Deobfuscate / rename final files: into other directory, nicer logging, nicer naming
* Deobfuscate / rename final files: black formatting
* Deobfuscate / rename final files: other order of tests
* Deobfuscate / rename final files: only if all_ok and not nzb_list
* Deobfuscate final files: retry commit
* Deobfuscate final files: feedback from Safihre
* Deobfuscate final files: create option in Special interface
* deobfuscate filenames: better logging, typo's
* Also find passwords which are not at the end of the file
* reformat file according to black code formatter
* Revert "reformat file according to black code formatter"
This reverts commit c7b16a12
* reformat file according to sabnzbd code conventions in black code formatter
* add tests for scan_password in nzbstuff.py
* add instructions on how to format code when contributing to this repo
* Revert "add instructions on how to format code when contributing to this repo"
This reverts commit ef6efd25
* add tests for file name extraction
* fix tests
echo "Bundled par2cmdline-turbo is already at version $VERSION"
exit 0
fi
git config user.name "SABnzbd Automation"
git config user.email "bugs@sabnzbd.org"
git add macos/par2 win/par2
git commit -m "par2cmdline-turbo $VERSION"
# Skip the push if an open PR already contains these exact binaries
OPEN_PRS=$(gh pr list --head "$BRANCH" --state open --json number --jq length)
if [ "$OPEN_PRS" != "0" ] && git fetch origin "$BRANCH" && git diff --quiet FETCH_HEAD HEAD -- macos/par2 win/par2; then
echo "Existing pull request already updates par2cmdline-turbo to $VERSION"
exit 0
fi
git push --force origin "HEAD:refs/heads/$BRANCH"
if [ "$OPEN_PRS" = "0" ]; then
gh pr create --head "$BRANCH" --title "par2cmdline-turbo $VERSION" --body "Automated update of the bundled par2cmdline-turbo binaries to version $VERSION.
SABnzbd is an Open Source Binary Newsreader written in Python.
@@ -18,15 +16,15 @@ If you want to know more you can head over to our website: https://sabnzbd.org.
SABnzbd has a few dependencies you'll need before you can get running. If you've previously run SABnzbd from one of the various Linux packages, then you likely already have all the needed dependencies. If not, here's what you're looking for:
-`python` (Python 3.5 and higher, often called `python3`)
- Python modules listed in `requirements.txt`
-`python` (Python 3.10 and above, often called `python3`)
- Python modules listed in `requirements.txt`. Install with `python3 -m pip install -r requirements.txt`
-`par2` (Multi-threaded par2 installation guide can be found [here](https://sabnzbd.org/wiki/installation/multicore-par2))
-`unrar` (make sure you get the "official" non-free version of unrar)
Optional:
- See `requirements.txt`
Your package manager should supply these. If not, we've got links in our [installation guide](https://github.com/sabnzbd/sabnzbd/blob/master/INSTALL.txt).
Your package manager should supply these. If not, we've got links in our [installation guide](https://sabnzbd.org/wiki/installation/install-off-modules).
## Running SABnzbd from source
@@ -68,3 +66,12 @@ Conditions:
- Bugfixes created specifically for a release branch are done there (because they are specific, they're not cherry-picked to `develop`).
- Bugfixes done on `develop` may be cherry-picked to a release branch.
- We will not release a 1.0.2 if a 1.1.0 has already been released.
## Privacy Policy
This program will not transfer any information to other networked systems unless
specifically requested by the user or the person installing or operating it.
## Code Signing Policy
For our Windows release, free code signing is provided by [SignPath.io](https://signpath.io), certificate by [SignPath Foundation](https://signpath.org).
LangStringMsgNoWin7${LANG_ENGLISH}"SABnzbd only supports Windows 8.1 and above."
LangStringMsgNoWin7${LANG_CZECH}"SABnzbd podporuje pouze Windows 8.1 a novější."
LangStringMsgNoWin7${LANG_DANISH}"SABnzbd understøtter kun Windows 8.1 og nyere."
LangStringMsgNoWin7${LANG_GERMAN}"SABnzbd unterstützt nur Windows 8.1 und höher."
LangStringMsgNoWin7${LANG_SPANISH}"SABnzbd solo es compatible con Windows 8.1 y superiores."
LangStringMsgNoWin7${LANG_FINNISH}"SABnzbd tukee vain Windows 8.1:tä ja uudempia."
LangStringMsgNoWin7${LANG_FRENCH}"SABnzbd n'est compatible qu'avec Windows 8.1 et plus."
LangStringMsgNoWin7${LANG_HEBREW}"SABnzbd תומך רק במערכות Windows 8.1 ומעלה."
LangStringMsgNoWin7${LANG_ITALIAN}"SABnzbd supporta solo Windows 8.1 e versioni successive."
LangStringMsgNoWin7${LANG_NORWEGIAN}"SABnzbd støtter kun Windows 8.1 og nyere."
LangStringMsgNoWin7${LANG_DUTCH}"SABnzbd ondersteund alleen Windows 8.1 en hoger."
LangStringMsgNoWin7${LANG_POLISH}"SABnzbd obsługuje tylko Windows 8.1 i nowsze."
LangStringMsgNoWin7${LANG_PORTUGUESEBR}"O SABnzbd oferece suporte apenas ao Windows 8.1 e superior."
LangStringMsgNoWin7${LANG_ROMANIAN}"SABnzbd acceptă doar Windows 8.1 și versiunile ulterioare."
LangStringMsgNoWin7${LANG_RUSSIAN}"SABnzbd поддерживает только Windows 8.1 и более новые."
LangStringMsgNoWin7${LANG_SERBIAN}"SABnzbd подржава само Windows 8.1 и новије."
LangStringMsgNoWin7${LANG_SWEDISH}"SABnzbd stöder endast Windows 8.1 och senare."
LangStringMsgNoWin7${LANG_TURKISH}"SABnzbd sadece Windows 8.1 ve üzerini destekler."
LangStringMsgNoWin7${LANG_SIMPCHINESE}"SABnzbd 仅支持 Windows 8.1 及更高版本。"
LangStringMsgARM64Notice${LANG_ENGLISH}"An ARM version of SABnzbd is available on our Downloads page. This installer only contains the regular version.$\nPress OK to continue or Cancel to exit."
LangStringMsgARM64Notice${LANG_CZECH}"Na naší stránce „Ke stažení“ je k dispozici verze SABnzbd pro architekturu ARM. Tento instalační program obsahuje pouze standardní verzi.$\nStiskněte tlačítko OK pro pokračování nebo Zrušit pro ukončení."
LangStringMsgARM64Notice${LANG_DANISH}"En ARM-version af SABnzbd er tilgængelig på vores downloadside. Dette installationsprogram indeholder kun den almindelige version.$\nTryk på OK for at fortsætte eller Annuller for at afslutte."
LangStringMsgARM64Notice${LANG_GERMAN}"Eine ARM-Version von SABnzbd ist auf unserer Downloads-Seite verfügbar. Dieses Installationsprogramm enthält nur die reguläre Version.$\nKlicken Sie auf OK, um fortzufahren, oder auf Abbrechen, um zu beenden."
LangStringMsgARM64Notice${LANG_SPANISH}"Hay una versión ARM de SABnzbd disponible en nuestra página de descargas. Este instalador solo contiene la versión normal.$\nPulsa Aceptar para continuar o Cancelar para salir."
LangStringMsgARM64Notice${LANG_FINNISH}"An ARM version of SABnzbd is available on our Downloads page. This installer only contains the regular version.$\nPress OK to continue or Cancel to exit."
LangStringMsgARM64Notice${LANG_FRENCH}"Une version ARM de SABnzbd est disponible sur notre page de téléchargement. Ce programme d'installation ne contient que la version standard.$\nCliquez sur OK pour continuer ou sur Annuler pour quitter."
LangStringMsgARM64Notice${LANG_HEBREW}"גרסת ARM של SABnzbd זמינה בעמוד ההורדות שלנו. תוכנת התקנה זו מכילה רק את הגרסה הרגילה.$\nלחץ על אישור כדי להמשיך או על ביטול כדי לצאת."
LangStringMsgARM64Notice${LANG_ITALIAN}"Una versione ARM di SABnzbd è disponibile nella nostra pagina dei download. Questo programma di installazione contiene solo la versione normale.$\nPremi OK per continuare o Annulla per uscire."
LangStringMsgARM64Notice${LANG_NORWEGIAN}"An ARM version of SABnzbd is available on our Downloads page. This installer only contains the regular version.$\nPress OK to continue or Cancel to exit."
LangStringMsgARM64Notice${LANG_DUTCH}"Er is een ARM versie van SABnzbd beschikbaar op onze Downloads pagina. Deze installatie bevat alleen de normale (niet-ARM) versie.$\nKlik OK om door te gaan of Annuleren om af te breken."
LangStringMsgARM64Notice${LANG_POLISH}"An ARM version of SABnzbd is available on our Downloads page. This installer only contains the regular version.$\nPress OK to continue or Cancel to exit."
LangStringMsgARM64Notice${LANG_PORTUGUESEBR}"An ARM version of SABnzbd is available on our Downloads page. This installer only contains the regular version.$\nPress OK to continue or Cancel to exit."
LangStringMsgARM64Notice${LANG_ROMANIAN}"An ARM version of SABnzbd is available on our Downloads page. This installer only contains the regular version.$\nPress OK to continue or Cancel to exit."
LangStringMsgARM64Notice${LANG_RUSSIAN}"An ARM version of SABnzbd is available on our Downloads page. This installer only contains the regular version.$\nPress OK to continue or Cancel to exit."
LangStringMsgARM64Notice${LANG_SERBIAN}"An ARM version of SABnzbd is available on our Downloads page. This installer only contains the regular version.$\nPress OK to continue or Cancel to exit."
LangStringMsgARM64Notice${LANG_SWEDISH}"An ARM version of SABnzbd is available on our Downloads page. This installer only contains the regular version.$\nPress OK to continue or Cancel to exit."
LangStringMsgARM64Notice${LANG_TURKISH}"SABnzbd'nin ARM sürümü İndirmeler sayfamızda mevcuttur. Bu kurulum programı sadece normal sürümü içermektedir.$\nDevam etmek için Tamam'a veya çıkmak için İptal'e tıklayın."
LangStringMsgARM64Notice${LANG_SIMPCHINESE}"我们的下载页面提供 SABnzbd 的 ARM 版本。此安装程序仅包含常规版本。$\n按“确定”继续,或按“取消”退出。"
LangStringMsgShutting${LANG_ENGLISH}"Shutting down SABnzbd"
- NZBs arrive via UI/API/URL; `urlgrabber.py` fetches remote NZBs, `nzbparser.py` turns them into `NzbObject`s, and `nzbqueue.NzbQueue` stores ordered jobs with priorities and categories.
2. **Queue to articles**
- When servers need work, `NzbQueue.get_articles` (called from `Server.get_article` in `downloader.py`) hands out batches of `Article`s per server, respecting retention, priority, and forced/paused items.
3. **Downloader setup**
- `Downloader` thread loads server configs (`config.get_servers`), instantiates `Server` objects (per host/port/SSL/threads), and spawns `NewsWrapper` instances per configured connection.
- A `selectors.DefaultSelector` watches all sockets; `BPSMeter` tracks throughput and speed limits; timers manage server penalties/restarts.
- `Server.request_addrinfo` resolves fastest address; `NewsWrapper` builds an `NNTP` socket, wraps SSL if needed, sets non-blocking, and registers with the selector.
- First server greeting (200/201) is queued; `finish_connect` drives the login handshake (`AUTHINFO USER/PASS`) and handles temporary (480) or permanent (400/502) errors.
5. **Request scheduling & pipelining**
- `write()` chooses the next article command (`STAT/HEAD` for precheck, `BODY` or `ARTICLE` otherwise).
- Concurrency is limited by `server.pipelining_requests`; commands are queued and sent with `sock.sendall`, so there is no local send buffer.
- Sockets stay registered for `EVENT_WRITE`: without write readiness events, a temporarily full kernel send buffer could stall queued commands when there is nothing to read, so WRITE interest is needed to resume sending promptly.
6. **Receiving data**
- Selector events route to `process_nw_read`; `NewsWrapper.read` pulls bytes (SSL optimized via sabctools), parses NNTP responses, and calls `on_response`.
- `Downloader.decode` hands responses to `decoder.decode`, which yEnc/UU decodes, CRC-checks, and stores payloads in `ArticleCache` (memory or disk spill).
- Articles with DMCA/bad data trigger retry on other servers until `max_art_tries` is exceeded.
8. **Assembly to files**
- `Assembler` worker consumes decoded pieces, writes to the target file, updates CRC, and cleans admin markers. It guards disk space (`diskspace_check`) and schedules direct unpack or PAR2 handling when files finish.
9. **Queue bookkeeping**
- `NzbQueue.register_article` records success/failure; completed files advance NZF/NZO state. If all files done, the job moves to post-processing (`PostProcessor.process`), which runs `newsunpack`, scripts, sorting, etc.
10. **Control & resilience**
- Pausing/resuming (`Downloader.pause/resume`), bandwidth limiting, and sleep tuning happen in the main loop.
- Errors/timeouts lead to `reset_nw` (close socket, return article, maybe penalize server). Optional servers can be temporarily disabled; required ones schedule resumes.
- Forced disconnect/shutdown drains sockets, refreshes DNS, and exits cleanly.
@@ -9,7 +9,7 @@ BY EXERCISING ANY RIGHTS TO THE WORK PROVIDED HERE, YOU ACCEPT AND AGREE TO BE B
1. Definitions
1. "Adaptation" means a work based upon the Work, or upon the Work and other pre-existing works, such as a translation, adaptation, derivative work, arrangement of music or other alterations of a literary or artistic work, or phonogram or performance and includes cinematographic adaptations or any other form in which the Work may be recast, transformed, or adapted including in any form recognizably derived from the original, except that a work that constitutes a Collection will not be considered an Adaptation for the purpose of this License. For the avoidance of doubt, where the Work is a musical work, performance or phonogram, the synchronization of the Work in timed-relation with a moving image ("synching") will be considered an Adaptation for the purpose of this License.
1. "Adaptation" means a work based upon the Work, or upon the Work and other pre-existing works, such as a translation, adaptation, derivative work, arrangement of music or other alterations of a literary or artistic work, or phonogram or performance and includes cinematographic adaptations or any other form in which the Work may be recast, transformed, or adapted including in any form recognizably derived from the original, except that a work that constitutes a Collection will not be considered an Adaptation for the purpose of this License. For the avoidance of doubt, where the Work is a musical work, performance or phonogram, the synchronization of the Work in timed-relation with a moving image ("syncing") will be considered an Adaptation for the purpose of this License.
2. "Collection" means a collection of literary or artistic works, such as encyclopedias and anthologies, or performances, phonograms or broadcasts, or other works or subject matter other than works listed in Section 1(f) below, which, by reason of the selection and arrangement of their contents, constitute intellectual creations, in which the Work is included in its entirety in unmodified form along with one or more other contributions, each constituting separate and independent works in themselves, which together are assembled into a collective whole. A work that constitutes a Collection will not be considered an Adaptation (as defined above) for the purposes of this License.
3. "Distribute" means to make available to the public the original and copies of the Work or Adaptation, as appropriate, through sale or other transfer of ownership.
4. "Licensor" means the individual, individuals, entity or entities that offer(s) the Work under the terms of this License.
@@ -44,7 +44,7 @@ The above rights may be exercised in all media and formats whether now known or
5. Representations, Warranties and Disclaimer
UNLESS OTHERWISE MUTUALLY AGREED TO BY THE PARTIES IN WRITING, LICENSOR OFFERS THE WORK AS-IS AND MAKES NO REPRESENTATIONS OR WARRANTIES OF ANY KIND CONCERNING THE WORK, EXPRESS, IMPLIED, STATUTORY OR OTHERWISE, INCLUDING, WITHOUT LIMITATION, WARRANTIES OF TITLE, MERCHANTIBILITY, FITNESS FOR A PARTICULAR PURPOSE, NONINFRINGEMENT, OR THE ABSENCE OF LATENT OR OTHER DEFECTS, ACCURACY, OR THE PRESENCE OF ABSENCE OF ERRORS, WHETHER OR NOT DISCOVERABLE. SOME JURISDICTIONS DO NOT ALLOW THE EXCLUSION OF IMPLIED WARRANTIES, SO SUCH EXCLUSION MAY NOT APPLY TO YOU.
UNLESS OTHERWISE MUTUALLY AGREED TO BY THE PARTIES IN WRITING, LICENSOR OFFERS THE WORK AS-IS AND MAKES NO REPRESENTATIONS OR WARRANTIES OF ANY KIND CONCERNING THE WORK, EXPRESS, IMPLIED, STATUTORY OR OTHERWISE, INCLUDING, WITHOUT LIMITATION, WARRANTIES OF TITLE, MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE, NONINFRINGEMENT, OR THE ABSENCE OF LATENT OR OTHER DEFECTS, ACCURACY, OR THE PRESENCE OF ABSENCE OF ERRORS, WHETHER OR NOT DISCOVERABLE. SOME JURISDICTIONS DO NOT ALLOW THE EXCLUSION OF IMPLIED WARRANTIES, SO SUCH EXCLUSION MAY NOT APPLY TO YOU.
6. Limitation on Liability. EXCEPT TO THE EXTENT REQUIRED BY APPLICABLE LAW, IN NO EVENT WILL LICENSOR BE LIABLE TO YOU ON ANY LEGAL THEORY FOR ANY SPECIAL, INCIDENTAL, CONSEQUENTIAL, PUNITIVE OR EXEMPLARY DAMAGES ARISING OUT OF THIS LICENSE OR THE USE OF THE WORK, EVEN IF LICENSOR HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGES.
/* Placeholder — themes live in glitter.css; this file only populates the scheme dropdown */
Loaded 100 of 557 files, more files were not shown because too many files have changed in this diff.
Show more
Reference in new issue
Block a user
Blocking a user prevents them from interacting with repositories, such as opening or commenting on pull requests or issues. Learn more about blocking a user.