Compare commits

...

99 Commits

Author SHA1 Message Date
Safihre
16618b3af2 Set version to 3.2.0 2021-02-26 10:30:00 +01:00
Safihre
0e5c0f664f Merge branch '3.2.x' 2021-02-26 10:29:39 +01:00
Safihre
7be9281431 Update text files for 3.2.0
draft release
2021-02-26 09:56:47 +01:00
Safihre
ee0327fac1 Update macOS build Python to 3.9.2 2021-02-26 09:44:51 +01:00
Safihre
9930de3e7f Log all nzo_info when adding NZB's
Relates to #1806
2021-02-26 09:18:14 +01:00
Sander
e8503e89c6 handle gracefully if no malloc_trim() available (#1800) 2021-02-26 09:18:00 +01:00
puzzledsab
1d9ed419eb Remove some redundant ifs (#1791) 2021-02-26 09:17:29 +01:00
Safihre
0207652e3e Update text files for 3.2.0RC2
draft release
2021-02-08 21:02:38 +01:00
Safihre
0f1e99c5cb Update translatable texts 2021-02-08 13:29:16 +01:00
puzzledsab
f134bc7efb Right-to-Left support for Glitter and Config (#1776)
* 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>
2021-02-08 13:23:03 +01:00
puzzledsab
dcd7c7180e Do full server check when there are busy_threads (#1786)
* Do full server check when there are busy_threads

* Reduce next_article_search delay to 0.5s
2021-02-08 13:19:38 +01:00
jcfp
fbbfcd075b fix bonjour with localhost, retire LOCALHOSTS constant (#1782)
* fix bonjour with localhost, retire LOCALHOSTS constant

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

* refuse to send ssdp description_xml to outsiders
2021-02-08 13:19:30 +01:00
Safihre
f42d2e4140 Rename Glitter Default to Light and make Auto the new Default 2021-02-05 15:01:28 +01:00
Sam Edwards
88882cebbc Support for auto night mode switching in Glitter (#1783) 2021-02-05 15:01:13 +01:00
Safihre
17a979675c Do not re-release from GA when the release tag is pushed 2021-02-05 15:01:04 +01:00
Safihre
4642850c79 Set macOS Python installer target to "/" 2021-02-05 15:01:00 +01:00
Safihre
e8d6eebb04 Set version to 3.1.1 2020-11-11 22:04:44 +01:00
Safihre
864c5160c0 Merge branch '3.1.x' 2020-11-11 22:01:20 +01:00
Safihre
99b5a00c12 Update text files for 3.1.1 2020-11-11 21:56:15 +01:00
Safihre
85ee1f07d7 Do not crash if we cannot format the error message 2020-11-08 15:06:50 +01:00
exizak42
e58b4394e0 Separate email message lines are with CRLF (#1671)
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
2020-11-08 14:44:44 +01:00
Safihre
1e91a57bf1 It was not possible to set directory-settings to empty values 2020-11-06 16:14:53 +01:00
Safihre
39cee52a7e Update text files for 3.1.1RC1 2020-11-02 20:03:43 +01:00
Safihre
72068f939d Improve handling of binary restarts (macOS / Windows) 2020-11-02 19:57:57 +01:00
Safihre
096d0d3cad Deobfuscate-during-download did not work
https://forums.sabnzbd.org/viewtopic.php?f=3&t=25037
2020-11-01 15:35:09 +01:00
Safihre
2472ab0121 Python 3.5 does not know ssl.PROTOCOL_TLS_SERVER
Closes #1658
2020-10-27 15:52:28 +01:00
Safihre
00421717b8 Queue Repair would fail if Rating is enabled
Closes #1649
2020-10-24 11:10:03 +02:00
Safihre
ae96d93f94 Set version to 3.1.0 2020-10-16 17:02:28 +02:00
Safihre
8522c40c8f Merge branch '3.1.x' 2020-10-16 16:58:58 +02:00
Safihre
23f86e95f1 Update text files for 3.1.0 2020-10-16 16:42:35 +02:00
Safihre
eed2045189 After pre-check the job was not restored to the original spot 2020-10-16 16:27:51 +02:00
Safihre
217785bf0f Applying Filters to a feed would result in crash
Closes #1634
2020-10-15 18:07:06 +02:00
Safihre
6aef50dc5d Update text files for 3.1.0RC3 2020-10-02 11:34:21 +02:00
Safihre
16b6e3caa7 Notify users of Deobfuscate.py that it is now part of SABnzbd 2020-09-29 14:08:51 +02:00
Safihre
3de4c99a8a Only set the "Waiting" status when the job hits post-processing
https://forums.sabnzbd.org/viewtopic.php?f=11&t=24969
2020-09-29 13:51:15 +02:00
Safihre
980aa19a75 Only run Windows Service code when executed from the executables
Could be made to work with the from-sources code.. But seems like very small usecase.
Closes #1623
2020-09-29 10:42:23 +02:00
Safihre
fb4b57e056 Update text files for 3.1.0RC2 2020-09-27 17:19:34 +02:00
Safihre
03638365ea Set execute bit on Deobfuscate.py 2020-09-27 17:17:30 +02:00
Safihre
157cb1c83d Handle failing RSS-feeds for feedparser 6.0.0+
Closes #1621
Now throws warnings (that can be disabled, helpfull_warnings) if readout failed.
2020-09-27 13:32:38 +02:00
Safihre
e51f11c2b1 Do not crash if attributes file is not present 2020-09-25 10:50:19 +02:00
Safihre
1ad0961dd8 Existing files were not parsed when re-adding a job 2020-09-25 10:49:50 +02:00
Safihre
46ff7dd4e2 Do not crash if we can't save attributes, the job might be gone 2020-09-25 10:03:05 +02:00
Safihre
8b067df914 Correctly parse failed_only for Plush 2020-09-23 16:56:57 +02:00
Safihre
ef43b13272 Assume RarFile parses the correct filepaths for the RAR-volumes
Parsing UTF8 from command-line still fails.
https://forums.sabnzbd.org/viewtopic.php?p=122267#p122267
2020-09-21 22:12:43 +02:00
Safihre
e8e9974224 work_name would not be sanatized when adding NZB's
Closes #1615
Now with tests, yeah.
2020-09-21 22:12:34 +02:00
Safihre
feebbb9f04 Merge branch '3.0.x' 2020-09-13 16:40:43 +02:00
Safihre
bc4f06dd1d Limit feedparser<6.0.0 for 3.0.x 2020-09-13 16:40:14 +02:00
Safihre
971e4fc909 Merge branch '3.0.x' 2020-08-30 20:58:31 +02:00
Safihre
51cc765949 Update text files for 3.0.2 2020-08-30 20:50:45 +02:00
Safihre
19c6a4fffa Propagation delay label was shown even if no delay was activated 2020-08-29 16:46:16 +02:00
Safihre
105ac32d2f Reading RSS feed with no categories set could result in crash
Closes #1589
2020-08-28 10:16:49 +02:00
Safihre
57550675d2 Removed logging in macOS sabApp that resulted in double logging 2020-08-28 10:16:41 +02:00
Safihre
e674abc5c0 Update text files for 3.0.2RC2 2020-08-26 08:56:29 +02:00
Safihre
f965c96f51 Change the macOS power assertion to NoIdleSleep 2020-08-26 08:50:54 +02:00
Safihre
c76b8ed9e0 End-of-queue-script did not run on Windows due to long-path
https://forums.sabnzbd.org/viewtopic.php?f=3&t=24918

Will refactor this so they all call 1 function.
2020-08-24 11:28:14 +02:00
Safihre
4fbd0d8a7b Check if name is a string before switching to nzbfile in addfile
Closes #1584
2020-08-24 09:05:25 +02:00
Safihre
2186c0fff6 Update text files for 3.0.2 RC 1 2020-08-21 15:42:35 +02:00
Safihre
1adca9a9c1 Do not crash if certifi certificates are not available
This could happen on Windows, due to overactive virus scanners
2020-08-21 15:26:06 +02:00
Safihre
9408353f2b Priority was not parsed correctly if supplied as string 2020-08-21 15:12:09 +02:00
Safihre
84f4d453d2 Permissions would be set even if user didn't set any
Windows developers like me shouldn't do permissions stuff..
2020-08-21 15:12:01 +02:00
Safihre
d10209f2a1 Extend tests of create_all_dirs to cover apply_umask=False 2020-08-21 15:11:53 +02:00
Safihre
3ae149c72f Split the make_mo.py command for NSIS 2020-08-19 22:21:02 +02:00
Safihre
47385acc3b Make sure we force the final_name to string on legacy get_attrib_file 2020-08-19 16:21:13 +02:00
Safihre
814eeaa900 Redesigned the saving of attributes
Now uses pickle, so that the type of the property is preserved.
Made flexible, so that more properties can be easily added later.
Closes #1575
2020-08-19 16:21:07 +02:00
Safihre
5f2ea13aad NzbFile comparison could crash when comparing finished_files
https://forums.sabnzbd.org/viewtopic.php?f=3&t=24902&p=121748
2020-08-19 08:50:06 +02:00
Safihre
41ca217931 Merge branch '3.0.x' 2020-08-18 11:05:50 +02:00
Safihre
b57d36e8dd Set version information to 3.0.1 2020-08-18 11:05:36 +02:00
Safihre
9a4be70734 List Cheetah minimal version in requirements.txt 2020-08-18 08:21:20 +02:00
Safihre
a8443595a6 Generalize use of certifi module 2020-08-18 08:20:47 +02:00
Safihre
fd0a70ac58 Update text files for 3.0.1 2020-08-17 16:52:23 +02:00
Safihre
8a8685c968 Permissions should only be applied if requested
Corrects 050b925f7b
2020-08-16 18:28:39 +02:00
Safihre
9e6cb8da8e Temporarily set cheroot version due to it breaking our tests
cherrypy/cheroot/issues/312
2020-08-16 18:28:13 +02:00
Safihre
054ec54d51 Basic authentication option was broken
Closes #1571
2020-08-10 15:34:01 +02:00
Safihre
272ce773cb Update text files for 3.0.1RC1 2020-08-07 15:28:11 +02:00
Safihre
050b925f7b Permissions were not set correctly when creating directories (#1568)
Restores changes made in d2e0ebe
2020-08-07 15:22:53 +02:00
Safihre
0087940898 Merge branch '3.0.x' into master 2020-08-02 09:46:41 +02:00
Safihre
e323c014f9 Set version information to 3.0.0 2020-08-01 16:17:08 +02:00
Safihre
cc465c7554 Update text files for 3.0.0
🎉🎉
2020-08-01 15:59:30 +02:00
Safihre
14cb37564f Update translate-link in SABnzbd 2020-07-19 13:01:39 +02:00
Safihre
094db56c3b Default-text for Automatically sort queue 2020-07-16 22:29:02 +02:00
Safihre
aabb709b8b Update text files for 3.0.0 RC 2 2020-07-15 14:10:35 +02:00
Safihre
0833dd2db9 Update translatable texts in 3.0.x branch 2020-07-15 14:07:21 +02:00
Safihre
cd3f912be4 RAR-renamer should be run on badly named RAR-files
https://forums.sabnzbd.org/viewtopic.php?f=2&t=24514&p=121433
2020-07-15 14:01:48 +02:00
Safihre
665c516db6 Only really run pre-script when it is set 2020-07-12 14:20:18 +02:00
Safihre
b670da9fa0 Always use Default-priority when creating NZB-objects
Closes #1552
2020-07-12 14:03:07 +02:00
Safihre
80bee9bffe Search-icon would be shown on top of drop-downs
Closes #1545
2020-06-30 12:57:28 +02:00
Safihre
d85a70e8ad Always report API paused status as a boolean
Closes #1542
2020-06-30 10:26:34 +02:00
Safihre
8f21533e76 Set version to 2.3.9 2019-05-24 11:39:14 +02:00
Safihre
89996482a1 Merge branch '2.3.x' 2019-05-24 09:33:12 +02:00
Safihre
03c10dce91 Update text files for 2.3.9 2019-05-24 09:32:34 +02:00
Safihre
bd5331be05 Merge branch 'develop' into 2.3.x 2019-05-24 09:12:02 +02:00
Safihre
46e1645289 Correct typo in release notes 2019-05-18 10:56:39 +02:00
Safihre
4ce3965747 Update text files for 2.3.9RC2 2019-05-18 09:56:05 +02:00
Safihre
9d4af19db3 Merge branch 'develop' into 2.3.x 2019-05-18 09:45:20 +02:00
Safihre
48e034f4be Update text files for 2.3.9RC1 2019-05-07 13:50:20 +02:00
Safihre
f8959baa2f Revert "Notify develop-users that we will switch to Python 3"
This reverts commit fb238af7de.
2019-05-07 13:35:13 +02:00
Safihre
8ed5997eae Merge branch 'develop' into 2.3.x 2019-05-07 13:10:10 +02:00
Safihre
daf9f50ac8 Set version to 2.3.8 2019-03-18 11:10:56 +01:00
Safihre
6b11013c1a Merge branch '2.3.x' 2019-03-18 11:09:35 +01:00
46 changed files with 1134 additions and 757 deletions

View File

@@ -59,7 +59,7 @@ jobs:
path: "*-win32-bin.zip"
name: Windows Windows standalone binary (32bit and legacy)
- name: Prepare official release
if: env.AUTOMATION_GITHUB_TOKEN
if: env.AUTOMATION_GITHUB_TOKEN && !startsWith(github.ref, 'refs/tags/')
run: python builder/package.py release
build_macos:
@@ -73,7 +73,7 @@ jobs:
# We need the official Python, because the GA ones only support newer macOS versions
# The deployment target is picked up by the Python build tools automatically
# If updated, make sure to also set LSMinimumSystemVersion in SABnzbd.spec
PYTHON_VERSION: 3.9.1
PYTHON_VERSION: 3.9.2
MACOSX_DEPLOYMENT_TARGET: 10.9
steps:
- uses: actions/checkout@v2
@@ -87,7 +87,7 @@ jobs:
if: steps.cache-python-download.outputs.cache-hit != 'true'
run: curl https://www.python.org/ftp/python/${PYTHON_VERSION}/python-${PYTHON_VERSION}-macosx10.9.pkg -o ~/python.pkg
- name: Install Python
run: sudo installer -pkg ~/python.pkg -target /Applications
run: sudo installer -pkg ~/python.pkg -target /
- name: Install Python dependencies
run: |
python3 --version
@@ -110,5 +110,5 @@ jobs:
path: "*-osx.dmg"
name: macOS binary (not notarized)
- name: Prepare official release
if: env.AUTOMATION_GITHUB_TOKEN
if: env.AUTOMATION_GITHUB_TOKEN && !startsWith(github.ref, 'refs/tags/')
run: python3 builder/package.py release

View File

@@ -1,7 +1,7 @@
Metadata-Version: 1.0
Name: SABnzbd
Version: 3.2.0RC1
Summary: SABnzbd-3.2.0RC1
Version: 3.2.0
Summary: SABnzbd-3.2.0
Home-page: https://sabnzbd.org
Author: The SABnzbd Team
Author-email: team@sabnzbd.org

View File

@@ -1,10 +1,10 @@
Release Notes - SABnzbd 3.2.0 Release Candidate 1
Release Notes - SABnzbd 3.2.0
=========================================================
## Changes since 3.1.1
- Python 3.6 is the minimum required version.
- The Windows installer can only be used on 64bit Windows 8.1 and
above. For 32bit systems or older Windows versions the
above. For 32bit systems or older Windows versions, the
standalone 32bit legacy version can be used.
- Post-processing can be aborted at any stage, including scripts.
- Improvements in the downloader to reduce CPU-load.
@@ -12,19 +12,22 @@ Release Notes - SABnzbd 3.2.0 Release Candidate 1
- Custom date ranges for server graphs can be selected.
- Keep track of article fetching success-rate of each server.
- Added option to add download quota warning for each server.
- Added option to add expiration waring for each server.
- Added option to add expiration warning for each server.
- Added `Minimum Free Space for Completed Download Folder` option.
- Added option to `Auto resume` for both `Minimum Free Space` settings.
- Added `Auto` option for Glitter that enables `Night` style
based on system settings. Default for new installations.
- Multiple additional Queue and History columns can be added.
- Added option to always use full screen width.
- Added option to always use full-screen width.
- Additional interface settings can be stored server-side.
- Right-to-Left support (Hebrew) for Glitter and Config.
- Using SSDP, SABnzbd instances are now listed in `Network` on Windows.
- Improvements to parsing of job name and filenames listed in the NZB.
- RSS titles can be edited.
- Prospective par2 will add blocks from all sets in a job.
- Sanitize all filenames to a maximum of 245 characters.
- Show commit hash when running from `git` sources.
- Notify through Notifications if new version is available.
- Notify through Notifications if a new version is available.
- Program shutdown time reduced to almost instant.
- Added `10 GB` test download.
- IPv6 is no longer preferred in HappyEyeballs address selection.
@@ -38,14 +41,14 @@ Release Notes - SABnzbd 3.2.0 Release Candidate 1
- Repairing or Retrying jobs could result in a crash.
- API-call `reset_quota` returned nothing.
- New categories were not always forced to lowercase.
- Broken downloads could result in crash during RAR-renaming
- Broken downloads could result in a crash during RAR-renaming
- Improved obfuscation detection for `Deobfuscate final filenames`.
- Keep original priority of duplicate jobs.
- Increase Maximum number of connections per server to `1000`.
- Increase the maximum number of connections per server to `1000`.
- Update encryption check to handle partially assembled files.
- Don't activate Windows notifications when running as service.
- Command line option `--console` did not work.
- Crash in API-call to delete history items for non-existing `nzo_id`.
- Don't activate Windows notifications when running as a service.
- Command-line option `--console` did not work.
- Crash in API-call to delete history items for nonexistent `nzo_id`.
- Prevent repetition of unwanted extension warnings.
- Correct notification category for failed URL fetches.
- Improvements to the `Add NZB` modal window.

View File

@@ -68,7 +68,9 @@ from sabnzbd.misc import (
get_serv_parms,
get_from_url,
upload_file_to_sabnzbd,
probablyipv4,
is_ipv4_addr,
is_localhost,
is_lan_addr,
)
from sabnzbd.filesystem import get_ext, real_path, long_path, globber_full, remove_file
from sabnzbd.panic import panic_tmpl, panic_port, panic_host, panic, launch_a_browser
@@ -533,7 +535,7 @@ def get_webhost(cherryhost, cherryport, https_port):
# Valid user defined name?
info = socket.getaddrinfo(cherryhost, None)
except socket.error:
if cherryhost not in LOCALHOSTS:
if not is_localhost(cherryhost):
cherryhost = "0.0.0.0"
try:
info = socket.getaddrinfo(localhost, None)
@@ -600,7 +602,7 @@ def get_webhost(cherryhost, cherryport, https_port):
except socket.error:
cherryhost = cherryhost.strip("[]")
if ipv6 and ipv4 and browserhost not in LOCALHOSTS:
if ipv6 and ipv4 and not is_localhost(browserhost):
sabnzbd.AMBI_LOCALHOST = True
logging.info("IPV6 has priority on this system, potential Firefox issue")
@@ -1489,34 +1491,37 @@ def main():
check_latest_version()
autorestarted = False
# bonjour/zeroconf needs an ip. Lets try to find it.
external_host = localipv4() # IPv4 address of the LAN interface. This is the normal use case
if not external_host:
# None, so no network / default route, so let's set to ...
external_host = "127.0.0.1"
elif probablyipv4(cherryhost) and cherryhost not in LOCALHOSTS + ("0.0.0.0", "::"):
# a hard-configured cherryhost other than the usual, so let's take that (good or wrong)
external_host = cherryhost
logging.debug("bonjour/zeroconf/SSDP using host: %s", external_host)
sabnzbd.zconfig.set_bonjour(external_host, cherryport)
# Start SSDP if SABnzbd is running exposed
if cherryhost not in LOCALHOSTS:
# Set URL for browser for external hosts
if enable_https:
ssdp_url = "https://%s:%s%s" % (external_host, cherryport, sabnzbd.cfg.url_base())
# Start SSDP and Bonjour if SABnzbd isn't listening on localhost only
if sabnzbd.cfg.enable_broadcast() and not is_localhost(cherryhost):
# Try to find a LAN IP address for SSDP/Bonjour
if is_lan_addr(cherryhost):
# A specific listening address was configured, use that
external_host = cherryhost
else:
ssdp_url = "http://%s:%s%s" % (external_host, cherryport, sabnzbd.cfg.url_base())
ssdp.start_ssdp(
external_host,
"SABnzbd",
ssdp_url,
"SABnzbd %s" % sabnzbd.__version__,
"SABnzbd Team",
"https://sabnzbd.org/",
"SABnzbd %s" % sabnzbd.__version__,
ssdp_broadcast_interval=sabnzbd.cfg.ssdp_broadcast_interval(),
)
# Fall back to the IPv4 address of the LAN interface
external_host = localipv4()
logging.debug("Using %s as host address for Bonjour and SSDP", external_host)
if is_lan_addr(external_host):
sabnzbd.zconfig.set_bonjour(external_host, cherryport)
# Set URL for browser for external hosts
ssdp_url = "%s://%s:%s%s" % (
("https" if enable_https else "http"),
external_host,
cherryport,
sabnzbd.cfg.url_base(),
)
ssdp.start_ssdp(
external_host,
"SABnzbd",
ssdp_url,
"SABnzbd %s" % sabnzbd.__version__,
"SABnzbd Team",
"https://sabnzbd.org/",
"SABnzbd %s" % sabnzbd.__version__,
ssdp_broadcast_interval=sabnzbd.cfg.ssdp_broadcast_interval(),
)
# Have to keep this running, otherwise logging will terminate
timer = 0

View File

@@ -4,7 +4,7 @@
#set global $root = '../../'#
#end if#
<!DOCTYPE HTML>
<html lang="$active_lang">
<html lang="$active_lang" #if $rtl#dir="rtl"#end if#>
<head>
<title>
SABnzbd $T('menu-config')

View File

@@ -59,7 +59,7 @@
<td class="controls">
<button type="button" class="btn btn-default testFeed" rel="$feed_item_html"><span class="glyphicon glyphicon-sort"></span> $T('button-preFeed')</button>
<input type="hidden" name="uri" value="$rss[$feed_item]['uris']" />
<button type="button" class="btn btn-default editFeed" rel="$feed_item_html"><span class="glyphicon glyphicon-pencil"></span> $T('Edit')</button>
<button type="button" class="btn btn-default editFeed" rel="$feed_item_html"><span class="glyphicon glyphicon-pencil"></span> $T('rss-edit')</button>
<button type="button" class="btn btn-default delFeed" rel="$feed_item_html"><span class="glyphicon glyphicon-trash"></span></button>
</td>
</tr>
@@ -92,7 +92,7 @@
<label class="config narrow" for="rss_rate">$T('opt-rss_rate')</label>
<input type="number" name="rss_rate" id="rss_rate" value="$rss_rate" min="15" max="1440" />
<button type="submit" class="btn btn-default"><span class="glyphicon glyphicon-ok"></span> $T('button-save')</button>
<span class="config narrow">&nbsp;&nbsp;$T('Next scan at:')&nbsp;$rss_next</span>
<span class="config narrow">&nbsp;&nbsp;$T('rss-nextscan'): $rss_next</span>
<span class="desc narrow">$T('explain-rss_rate')</span>
</div>
</fieldset>

View File

@@ -162,6 +162,7 @@ input[type="checkbox"]+.desc {
float: none;
overflow: hidden;
min-width: 555px;
position: relative;
}
.Key tr:nth-child(odd),
.tab-pane tr:nth-child(odd),
@@ -1168,6 +1169,27 @@ input[type="checkbox"] {
100% { transform: rotate(359deg); }
}
/***
RTL Fixes
***/
html[dir="rtl"] .col1 input[type='checkbox'],
html[dir="rtl"] .col2 h3 a {
left: 5px;
}
html[dir="rtl"] .modal-header .close {
float: left;
}
html[dir="rtl"] .Sorting .presets.float-left,
html[dir="rtl"] .checkbox-days {
float: none;
}
html[dir="rtl"] .Scheduling form[action="addSchedule"] input[type="checkbox"] {
right: 5px;
}
@media screen and (min-width: 1200px) {
.Categories input[name="dir"] {
max-width: 240px !important;

View File

@@ -1,6 +1,6 @@
<!DOCTYPE html>
<!--#set $active_lang=$active_lang.replace('_', '-').lower()#-->
<html lang="$active_lang" id="sabnzbd" data-bind="filedrop: { overlaySelector: '.main-filedrop', onFileDrop: addNZBFromFile }">
<html lang="$active_lang" <!--#if $rtl#-->dir="rtl"<!--#end if#--> id="sabnzbd" data-bind="filedrop: { overlaySelector: '.main-filedrop', onFileDrop: addNZBFromFile }">
<head>
<!--
Glitter V2
@@ -36,7 +36,7 @@
<link rel="stylesheet" type="text/css" href="./static/bootstrap/css/bootstrap.min.css?v=$version" />
<link rel="stylesheet" type="text/css" href="./static/stylesheets/glitter.css?v=$version" />
<link rel="stylesheet" type="text/css" href="./static/stylesheets/glitter.mobile.css?v=$version" media="all and (max-width: 768px)" />
<!--#if $color_scheme not in ('Default', '') #-->
<!--#if $color_scheme not in ('Light', '') #-->
<link rel="stylesheet" type="text/css" href="./static/stylesheets/colorschemes/${color_scheme}.css?v=$version"/>
<!--#end if#-->

View File

@@ -0,0 +1 @@
@import url('Night.css') screen and (prefers-color-scheme: dark);

View File

@@ -1979,6 +1979,45 @@ input[name="nzbURL"] {
}
}
/***
RTL Fixes
***/
html[dir="rtl"] .navbar-nav {
padding-right: 0;
}
html[dir="rtl"] .queue h2,
html[dir="rtl"] .history h2 {
float: right;
}
html[dir="rtl"] .dropdown-menu {
text-align: right;
direction: rtl;
}
html[dir="rtl"] .speedlimit-dropdown,
html[dir="rtl"] .progress-indicator,
html[dir="rtl"] #modal-item-filelist,
html[dir="rtl"] #modal-item-files .modal-title,
html[dir="rtl"] .info-container-box,
html[dir="rtl"] .queue-table,
html[dir="rtl"] .history-table {
direction: ltr;
}
html[dir="rtl"] .search-box a {
right: initial;
left: 8px;
}
html[dir="rtl"] .navbar-logo,
html[dir="rtl"] .info-container,
html[dir="rtl"] .modal-header .close,
html[dir="rtl"] #modal-options .modal-header a {
float: left;
}
/***
Bootstrap overwrites

View File

@@ -3771,6 +3771,16 @@ msgstr ""
msgid "Force Download"
msgstr ""
#. Config->RSS edit button
#: sabnzbd/skintext.py
msgid "Edit"
msgstr ""
#. Config->RSS when will be the next RSS scan
#: sabnzbd/skintext.py
msgid "Next scan at"
msgstr ""
#. Config->RSS table column header
#: sabnzbd/skintext.py
msgid "Filter"

View File

@@ -3946,6 +3946,16 @@ msgstr ""
msgid "Force Download"
msgstr ""
#. Config->RSS edit button
#: sabnzbd/skintext.py
msgid "Edit"
msgstr ""
#. Config->RSS when will be the next RSS scan
#: sabnzbd/skintext.py
msgid "Next scan at"
msgstr ""
#. Config->RSS table column header
#: sabnzbd/skintext.py
msgid "Filter"

View File

@@ -4054,6 +4054,16 @@ msgstr "Læs Feed"
msgid "Force Download"
msgstr "Gennemtving download"
#. Config->RSS edit button
#: sabnzbd/skintext.py
msgid "Edit"
msgstr ""
#. Config->RSS when will be the next RSS scan
#: sabnzbd/skintext.py
msgid "Next scan at"
msgstr ""
#. Config->RSS table column header
#: sabnzbd/skintext.py
msgid "Filter"

View File

@@ -4174,6 +4174,16 @@ msgstr "Feed lesen"
msgid "Force Download"
msgstr "Download erzwingen"
#. Config->RSS edit button
#: sabnzbd/skintext.py
msgid "Edit"
msgstr ""
#. Config->RSS when will be the next RSS scan
#: sabnzbd/skintext.py
msgid "Next scan at"
msgstr ""
#. Config->RSS table column header
#: sabnzbd/skintext.py
msgid "Filter"

View File

@@ -4166,6 +4166,16 @@ msgstr "Leer Fuente"
msgid "Force Download"
msgstr "Forzar Descarga"
#. Config->RSS edit button
#: sabnzbd/skintext.py
msgid "Edit"
msgstr ""
#. Config->RSS when will be the next RSS scan
#: sabnzbd/skintext.py
msgid "Next scan at"
msgstr ""
#. Config->RSS table column header
#: sabnzbd/skintext.py
msgid "Filter"

View File

@@ -4053,6 +4053,16 @@ msgstr "Lue syöte"
msgid "Force Download"
msgstr "Pakota lataus"
#. Config->RSS edit button
#: sabnzbd/skintext.py
msgid "Edit"
msgstr ""
#. Config->RSS when will be the next RSS scan
#: sabnzbd/skintext.py
msgid "Next scan at"
msgstr ""
#. Config->RSS table column header
#: sabnzbd/skintext.py
msgid "Filter"

View File

@@ -4182,6 +4182,16 @@ msgstr "Lire le flux RSS"
msgid "Force Download"
msgstr "Forcer le téléchargement"
#. Config->RSS edit button
#: sabnzbd/skintext.py
msgid "Edit"
msgstr ""
#. Config->RSS when will be the next RSS scan
#: sabnzbd/skintext.py
msgid "Next scan at"
msgstr ""
#. Config->RSS table column header
#: sabnzbd/skintext.py
msgid "Filter"

View File

File diff suppressed because it is too large Load Diff

View File

@@ -4029,6 +4029,16 @@ msgstr "Les kilde"
msgid "Force Download"
msgstr "Tving nedlasting"
#. Config->RSS edit button
#: sabnzbd/skintext.py
msgid "Edit"
msgstr ""
#. Config->RSS when will be the next RSS scan
#: sabnzbd/skintext.py
msgid "Next scan at"
msgstr ""
#. Config->RSS table column header
#: sabnzbd/skintext.py
msgid "Filter"

View File

@@ -4135,6 +4135,16 @@ msgstr "Uitlezen"
msgid "Force Download"
msgstr "Forceer download"
#. Config->RSS edit button
#: sabnzbd/skintext.py
msgid "Edit"
msgstr ""
#. Config->RSS when will be the next RSS scan
#: sabnzbd/skintext.py
msgid "Next scan at"
msgstr ""
#. Config->RSS table column header
#: sabnzbd/skintext.py
msgid "Filter"

View File

@@ -4039,6 +4039,16 @@ msgstr "Pobierz kanał"
msgid "Force Download"
msgstr "Wymuś pobranie"
#. Config->RSS edit button
#: sabnzbd/skintext.py
msgid "Edit"
msgstr ""
#. Config->RSS when will be the next RSS scan
#: sabnzbd/skintext.py
msgid "Next scan at"
msgstr ""
#. Config->RSS table column header
#: sabnzbd/skintext.py
msgid "Filter"

View File

@@ -4042,6 +4042,16 @@ msgstr "Ler Feed"
msgid "Force Download"
msgstr "Forçar Download"
#. Config->RSS edit button
#: sabnzbd/skintext.py
msgid "Edit"
msgstr ""
#. Config->RSS when will be the next RSS scan
#: sabnzbd/skintext.py
msgid "Next scan at"
msgstr ""
#. Config->RSS table column header
#: sabnzbd/skintext.py
msgid "Filter"

View File

@@ -4068,6 +4068,16 @@ msgstr "Citeşte Flux"
msgid "Force Download"
msgstr "Descărcare Forţată"
#. Config->RSS edit button
#: sabnzbd/skintext.py
msgid "Edit"
msgstr ""
#. Config->RSS when will be the next RSS scan
#: sabnzbd/skintext.py
msgid "Next scan at"
msgstr ""
#. Config->RSS table column header
#: sabnzbd/skintext.py
msgid "Filter"

View File

@@ -4027,6 +4027,16 @@ msgstr "Прочитать ленту"
msgid "Force Download"
msgstr "Загрузить принудительно"
#. Config->RSS edit button
#: sabnzbd/skintext.py
msgid "Edit"
msgstr ""
#. Config->RSS when will be the next RSS scan
#: sabnzbd/skintext.py
msgid "Next scan at"
msgstr ""
#. Config->RSS table column header
#: sabnzbd/skintext.py
msgid "Filter"

View File

@@ -4015,6 +4015,16 @@ msgstr "Читај фид"
msgid "Force Download"
msgstr "Натерај преузимање"
#. Config->RSS edit button
#: sabnzbd/skintext.py
msgid "Edit"
msgstr ""
#. Config->RSS when will be the next RSS scan
#: sabnzbd/skintext.py
msgid "Next scan at"
msgstr ""
#. Config->RSS table column header
#: sabnzbd/skintext.py
msgid "Filter"

View File

@@ -4028,6 +4028,16 @@ msgstr "Läs flöde"
msgid "Force Download"
msgstr "Tvinga nedladdning"
#. Config->RSS edit button
#: sabnzbd/skintext.py
msgid "Edit"
msgstr ""
#. Config->RSS when will be the next RSS scan
#: sabnzbd/skintext.py
msgid "Next scan at"
msgstr ""
#. Config->RSS table column header
#: sabnzbd/skintext.py
msgid "Filter"

View File

@@ -3960,6 +3960,16 @@ msgstr "读取 Feed"
msgid "Force Download"
msgstr "强制下载"
#. Config->RSS edit button
#: sabnzbd/skintext.py
msgid "Edit"
msgstr ""
#. Config->RSS when will be the next RSS scan
#: sabnzbd/skintext.py
msgid "Next scan at"
msgstr ""
#. Config->RSS table column header
#: sabnzbd/skintext.py
msgid "Filter"

View File

@@ -36,9 +36,9 @@ msgid ""
"reinstall the SABnzbd service. \\n\\nClick `OK` to remove the existing "
"services or `Cancel` to cancel this upgrade."
msgstr ""
"שירות SABnzbd Windows השתנה בגרסה SABnzbd 3.0.0. \\nתצטרך להתקין מחדש את "
"השירות SABnzbd. \\n\\nלחץ `אשר` כדי להסיר את השירותים הקיימים או `בטל` כדי "
"לבטל שדרוג זה."
"שירות Windows של SABnzbd השתנה ב־SABnzbd 3.0.0. \\nתצטרך להתקין מחדש את "
"השירות של SABnzbd. \\n\\nלחץ על `אישור` כדי להסיר את השירותים הקיימים או על "
"`ביטול` כדי לבטל שדרוג זה."
#: builder/win/NSIS_Installer.nsi
msgid ""
@@ -58,19 +58,19 @@ msgstr ""
#: builder/win/NSIS_Installer.nsi
msgid "This will uninstall SABnzbd from your system"
msgstr "זה יסיר את SABnzbd ממערכתך"
msgstr "זה יסיר את SABnzbd מהמערכת שלך"
#: builder/win/NSIS_Installer.nsi
msgid "Run at startup"
msgstr "הפעלה בהזנק"
msgstr "הרץ בהזנק"
#: builder/win/NSIS_Installer.nsi
msgid "Desktop Icon"
msgstr "צלמית שולחן עבודה"
msgstr "צור קיצור דרך בשולחן העבודה"
#: builder/win/NSIS_Installer.nsi
msgid "NZB File association"
msgstr "NZB שיוך קבצי"
msgstr "NZB שייך קבצי"
#: builder/win/NSIS_Installer.nsi
msgid "Delete Program"
@@ -85,9 +85,9 @@ msgid ""
"You cannot overwrite an existing installation. \\n\\nClick `OK` to remove "
"the previous version or `Cancel` to cancel this upgrade."
msgstr ""
"אינך יכול לדרוס התקנה קיימת.\\n\\nלחץ על `אישור` כדי להסיר את הגרסה הקודמת "
"אינך יכול לדרוס התקנה קיימת. \\n\\nלחץ על `אישור` כדי להסיר את הגרסה הקודמת "
"או על `ביטול` כדי לבטל שדרוג זה."
#: builder/win/NSIS_Installer.nsi
msgid "Your settings and data will be preserved."
msgstr "ההגדרות והנתונים שלך יישמרו."
msgstr "ההגדרות והנתונים שלך ישתמרו."

View File

@@ -59,7 +59,10 @@ elif os.name == "posix":
# See if we have Linux memory functions
try:
LIBC = ctypes.CDLL("libc.so.6")
LIBC.malloc_trim(0)
except:
# No malloc_trim(), probably because no libc
LIBC = None
pass
# Parse macOS version numbers

View File

@@ -63,6 +63,7 @@ from sabnzbd.encoding import xml_name
from sabnzbd.utils.servertests import test_nntp_server_dict
from sabnzbd.getipaddress import localipv4, publicipv4, ipv6, addresslookup
from sabnzbd.database import build_history_info, unpack_history_info, HistoryDB
from sabnzbd.lang import is_rtl
import sabnzbd.notifier
import sabnzbd.rss
import sabnzbd.emailer
@@ -1600,6 +1601,7 @@ def build_header(webdir="", output=None, trans_functions=True):
header["restart_req"] = sabnzbd.RESTART_REQ
header["pid"] = os.getpid()
header["active_lang"] = cfg.language()
header["rtl"] = is_rtl(header["active_lang"])
header["my_lcldata"] = clip_path(sabnzbd.DIR_LCLDATA)
header["my_home"] = clip_path(sabnzbd.DIR_HOME)

View File

@@ -282,7 +282,7 @@ helpfull_warnings = OptionBool("misc", "helpfull_warnings", True)
keep_awake = OptionBool("misc", "keep_awake", True)
win_menu = OptionBool("misc", "win_menu", True)
allow_incomplete_nzb = OptionBool("misc", "allow_incomplete_nzb", False)
enable_bonjour = OptionBool("misc", "enable_bonjour", True)
enable_broadcast = OptionBool("misc", "enable_broadcast", True)
max_art_opt = OptionBool("misc", "max_art_opt", False)
ipv6_hosting = OptionBool("misc", "ipv6_hosting", False)
fixed_ports = OptionBool("misc", "fixed_ports", False)

View File

@@ -75,7 +75,7 @@ DEF_INTERFACES = "interfaces"
DEF_EMAIL_TMPL = "email"
DEF_STDCONFIG = "Config"
DEF_STDINTF = "Glitter"
DEF_SKIN_COLORS = {"Glitter": "Default", "plush": "gold"}
DEF_SKIN_COLORS = {"Glitter": "Auto", "plush": "gold"}
DEF_MAIN_TMPL = os.path.normpath("templates/main.tmpl")
DEF_INI_FILE = "sabnzbd.ini"
DEF_HOST = "127.0.0.1"
@@ -124,8 +124,6 @@ CHEETAH_DIRECTIVES = {"directiveStartToken": "<!--#", "directiveEndToken": "#-->
IGNORED_FOLDERS = ("@eaDir", ".appleDouble")
LOCALHOSTS = ("localhost", "127.0.0.1", "[::1]", "::1")
# (MATCHER, [EXTRA, MATCHERS])
series_match = [
(compile(r"( [sS]|[\d]+)x(\d+)"), [compile(r"^[-\.]+([sS]|[\d])+x(\d+)"), compile(r"^[-\.](\d+)")]), # 1x01

View File

@@ -95,7 +95,7 @@ class Server:
self.busy_threads: List[NewsWrapper] = []
self.idle_threads: List[NewsWrapper] = []
self.next_article_search: int = 0
self.next_article_search: float = 0
self.active: bool = True
self.bad_cons: int = 0
self.errormsg: str = ""
@@ -480,7 +480,7 @@ class Downloader(Thread):
for server in self.servers:
# Skip this server if there's no point searching for new stuff to do
if server.next_article_search > now:
if not server.busy_threads and server.next_article_search > now:
continue
for nw in server.busy_threads[:]:
@@ -534,8 +534,8 @@ class Downloader(Thread):
article = sabnzbd.NzbQueue.get_article(server, self.servers)
if not article:
# Skip this server for 1 second
server.next_article_search = now + 1
# Skip this server for 0.5 second
server.next_article_search = now + 0.5
break
if server.retention and article.nzf.nzo.avg_stamp < now - server.retention:

View File

@@ -44,10 +44,11 @@ from sabnzbd.misc import (
calc_age,
int_conv,
get_base_url,
probablyipv4,
probablyipv6,
is_ipv4_addr,
is_ipv6_addr,
opts_to_pp,
get_server_addrinfo,
is_lan_addr,
)
from sabnzbd.filesystem import real_path, long_path, globber, globber_full, remove_all, clip_path, same_file
from sabnzbd.encoding import xml_name, utob
@@ -165,7 +166,7 @@ def check_hostname():
host = re.sub(":[0123456789]+$", "", host).lower()
# Fine if localhost or IP
if host == "localhost" or probablyipv4(host) or probablyipv6(host):
if host == "localhost" or is_ipv4_addr(host) or is_ipv6_addr(host):
return True
# Check on the whitelist
@@ -477,8 +478,11 @@ class MainPage:
cherrypy.request.remote.ip,
cherrypy.request.headers.get("User-Agent", "??"),
)
cherrypy.response.headers["Content-Type"] = "application/xml"
return utob(sabnzbd.utils.ssdp.server_ssdp_xml())
if is_lan_addr(cherrypy.request.remote.ip):
cherrypy.response.headers["Content-Type"] = "application/xml"
return utob(sabnzbd.utils.ssdp.server_ssdp_xml())
else:
return None
##############################################################################
@@ -509,7 +513,7 @@ class Wizard:
cfg.language.set(kwargs.get("lang"))
# Always setup Glitter
change_web_dir("Glitter - Default")
change_web_dir("Glitter - Auto")
info = build_header(sabnzbd.WIZARD_DIR)
info["certificate_validation"] = sabnzbd.CERTIFICATE_VALIDATION
@@ -1327,7 +1331,7 @@ SPECIAL_BOOL_LIST = (
"html_login",
"wait_for_dfolder",
"max_art_opt",
"enable_bonjour",
"enable_broadcast",
"warn_dupl_jobs",
"replace_illegal",
"backup_for_duplicates",

View File

@@ -92,99 +92,104 @@ def list_languages():
return lst
def is_rtl(lang):
return LanguageTable.get(lang, "en")[3]
# English name, native name, code page, right-to-left
LanguageTable = {
"aa": ("Afar", "Afaraf", 0),
"af": ("Afrikaans", "Afrikaans", 0),
"ak": ("Akan", "Akan", 0),
"sq": ("Albanian", "Shqip", 0),
"an": ("Aragonese", "Aragonés", 0),
"ae": ("Avestan", "Avesta", 0),
"ay": ("Aymara", "Aymararu", 0),
"bm": ("Bambara", "Bamanankan", 0),
"eu": ("Basque", "Euskara", 0),
"bi": ("Bislama", "Bislama", 0),
"bs": ("Bosnian", "Bosanskijezik", 0),
"br": ("Breton", "Brezhoneg", 0),
"ca": ("Catalan", "Català", 0),
"ch": ("Chamorro", "Chamoru", 0),
"kw": ("Cornish", "Kernewek", 0),
"co": ("Corsican", "Corsu", 0),
"hr": ("Croatian", "Hrvatski", 0),
"cs": ("Czech", "Cesky, ceština", 0),
"da": ("Danish", "Dansk", 0),
"nl": ("Dutch", "Nederlands", 0),
"en": ("English", "English", 0),
"eo": ("Esperanto", "Esperanto", 0),
"et": ("Estonian", "Eesti", 0),
"fo": ("Faroese", "Føroyskt", 0),
"fj": ("Fijian", "Vosa Vakaviti", 0),
"fi": ("Finnish", "Suomi", 0),
"fr": ("French", "Français", 0),
"gl": ("Galician", "Galego", 0),
"de": ("German", "Deutsch", 0),
"he": ("Hebrew", "עִבְרִית‎", 1255),
"hz": ("Herero", "Otjiherero", 0),
"ho": ("Hiri Motu", "Hiri Motu", 0),
"hu": ("Hungarian", "Magyar", 0),
"id": ("Indonesian", "Bahasa Indonesia", 0),
"ga": ("Irish", "Gaeilge", 0),
"io": ("Ido", "Ido", 0),
"is": ("Icelandic", "Íslenska", 0),
"it": ("Italian", "Italiano", 0),
"jv": ("Javanese", "BasaJawa", 0),
"rw": ("Kinyarwanda", "Ikinyarwanda", 0),
"kg": ("Kongo", "KiKongo", 0),
"kj": ("Kwanyama", "Kuanyama", 0),
"la": ("Latin", "Lingua latina", 0),
"lb": ("Luxembourgish", "Lëtzebuergesch", 0),
"lg": ("Luganda", "Luganda", 0),
"li": ("Limburgish", "Limburgs", 0),
"ln": ("Lingala", "Lingála", 0),
"lt": ("Lithuanian", "Lietuviukalba", 0),
"lv": ("Latvian", "Latviešuvaloda", 0),
"gv": ("Manx", "Gaelg", 0),
"mg": ("Malagasy", "Malagasy fiteny", 0),
"mt": ("Maltese", "Malti", 0),
"nb": ("Norwegian Bokmål", "Norsk bokmål", 0),
"nn": ("Norwegian Nynorsk", "Norsk nynorsk", 0),
"no": ("Norwegian", "Norsk", 0),
"oc": ("Occitan", "Occitan", 0),
"om": ("Oromo", "Afaan Oromoo", 0),
"pl": ("Polish", "Polski", 0),
"pt": ("Portuguese", "Português", 0),
"pt_BR": ("Portuguese Brazillian", "Português Brasileiro", 0),
"rm": ("Romansh", "Rumantsch grischun", 0),
"rn": ("Kirundi", "kiRundi", 0),
"ro": ("Romanian", "Româna", 1250),
"sc": ("Sardinian", "Sardu", 0),
"se": ("Northern Sami", "Davvisámegiella", 0),
"sm": ("Samoan", "Gagana fa'a Samoa", 0),
"gd": ("Gaelic", "Gàidhlig", 0),
"ru": ("Russian", "русский язык", 1251),
"sr": ("Serbian", "српски", 1251),
"sn": ("Shona", "Chi Shona", 0),
"sk": ("Slovak", "Slovencina", 0),
"sl": ("Slovene", "Slovenšcina", 0),
"st": ("Southern Sotho", "Sesotho", 0),
"es": ("Spanish Castilian", "Español, castellano", 0),
"su": ("Sundanese", "Basa Sunda", 0),
"sw": ("Swahili", "Kiswahili", 0),
"ss": ("Swati", "SiSwati", 0),
"sv": ("Swedish", "Svenska", 0),
"tn": ("Tswana", "Setswana", 0),
"to": ("Tonga (Tonga Islands)", "faka Tonga", 0),
"tr": ("Turkish", "Türkçe", 0),
"ts": ("Tsonga", "Xitsonga", 0),
"tw": ("Twi", "Twi", 0),
"ty": ("Tahitian", "Reo Tahiti", 0),
"wa": ("Walloon", "Walon", 0),
"cy": ("Welsh", "Cymraeg", 0),
"wo": ("Wolof", "Wollof", 0),
"fy": ("Western Frisian", "Frysk", 0),
"xh": ("Xhosa", "isi Xhosa", 0),
"yo": ("Yoruba", "Yorùbá", 0),
"zu": ("Zulu", "isi Zulu", 0),
"zh_CN": ("SimpChinese", "简体中文", 936),
"aa": ("Afar", "Afaraf", 0, False),
"af": ("Afrikaans", "Afrikaans", 0, False),
"ak": ("Akan", "Akan", 0, False),
"sq": ("Albanian", "Shqip", 0, False),
"an": ("Aragonese", "Aragonés", 0, False),
"ae": ("Avestan", "Avesta", 0, False),
"ay": ("Aymara", "Aymararu", 0, False),
"bm": ("Bambara", "Bamanankan", 0, False),
"eu": ("Basque", "Euskara", 0, False),
"bi": ("Bislama", "Bislama", 0, False),
"bs": ("Bosnian", "Bosanskijezik", 0, False),
"br": ("Breton", "Brezhoneg", 0, False),
"ca": ("Catalan", "Català", 0, False),
"ch": ("Chamorro", "Chamoru", 0, False),
"kw": ("Cornish", "Kernewek", 0, False),
"co": ("Corsican", "Corsu", 0, False),
"hr": ("Croatian", "Hrvatski", 0, False),
"cs": ("Czech", "Cesky, ceština", 0, False),
"da": ("Danish", "Dansk", 0, False),
"nl": ("Dutch", "Nederlands", 0, False),
"en": ("English", "English", 0, False),
"eo": ("Esperanto", "Esperanto", 0, False),
"et": ("Estonian", "Eesti", 0, False),
"fo": ("Faroese", "Føroyskt", 0, False),
"fj": ("Fijian", "Vosa Vakaviti", 0, False),
"fi": ("Finnish", "Suomi", 0, False),
"fr": ("French", "Français", 0, False),
"gl": ("Galician", "Galego", 0, False),
"de": ("German", "Deutsch", 0, False),
"he": ("Hebrew", "עִבְרִית‎", 1255, True),
"hz": ("Herero", "Otjiherero", 0, False),
"ho": ("Hiri Motu", "Hiri Motu", 0, False),
"hu": ("Hungarian", "Magyar", 0, False),
"id": ("Indonesian", "Bahasa Indonesia", 0, False),
"ga": ("Irish", "Gaeilge", 0, False),
"io": ("Ido", "Ido", 0, False),
"is": ("Icelandic", "Íslenska", 0, False),
"it": ("Italian", "Italiano", 0, False),
"jv": ("Javanese", "BasaJawa", 0, False),
"rw": ("Kinyarwanda", "Ikinyarwanda", 0, False),
"kg": ("Kongo", "KiKongo", 0, False),
"kj": ("Kwanyama", "Kuanyama", 0, False),
"la": ("Latin", "Lingua latina", 0, False),
"lb": ("Luxembourgish", "Lëtzebuergesch", 0, False),
"lg": ("Luganda", "Luganda", 0, False),
"li": ("Limburgish", "Limburgs", 0, False),
"ln": ("Lingala", "Lingála", 0, False),
"lt": ("Lithuanian", "Lietuviukalba", 0, False),
"lv": ("Latvian", "Latviešuvaloda", 0, False),
"gv": ("Manx", "Gaelg", 0, False),
"mg": ("Malagasy", "Malagasy fiteny", 0, False),
"mt": ("Maltese", "Malti", 0, False),
"nb": ("Norwegian Bokmål", "Norsk bokmål", 0, False),
"nn": ("Norwegian Nynorsk", "Norsk nynorsk", 0, False),
"no": ("Norwegian", "Norsk", 0, False),
"oc": ("Occitan", "Occitan", 0, False),
"om": ("Oromo", "Afaan Oromoo", 0, False),
"pl": ("Polish", "Polski", 0, False),
"pt": ("Portuguese", "Português", 0, False),
"pt_BR": ("Portuguese Brazillian", "Português Brasileiro", 0, False),
"rm": ("Romansh", "Rumantsch grischun", 0, False),
"rn": ("Kirundi", "kiRundi", 0, False),
"ro": ("Romanian", "Româna", 1250, False),
"sc": ("Sardinian", "Sardu", 0, False),
"se": ("Northern Sami", "Davvisámegiella", 0, False),
"sm": ("Samoan", "Gagana fa'a Samoa", 0, False),
"gd": ("Gaelic", "Gàidhlig", 0, False),
"ru": ("Russian", "русский язык", 1251, False),
"sr": ("Serbian", "српски", 1251, False),
"sn": ("Shona", "Chi Shona", 0, False),
"sk": ("Slovak", "Slovencina", 0, False),
"sl": ("Slovene", "Slovenšcina", 0, False),
"st": ("Southern Sotho", "Sesotho", 0, False),
"es": ("Spanish Castilian", "Español, castellano", 0, False),
"su": ("Sundanese", "Basa Sunda", 0, False),
"sw": ("Swahili", "Kiswahili", 0, False),
"ss": ("Swati", "SiSwati", 0, False),
"sv": ("Swedish", "Svenska", 0, False),
"tn": ("Tswana", "Setswana", 0, False),
"to": ("Tonga (Tonga Islands)", "faka Tonga", 0, False),
"tr": ("Turkish", "Türkçe", 0, False),
"ts": ("Tsonga", "Xitsonga", 0, False),
"tw": ("Twi", "Twi", 0, False),
"ty": ("Tahitian", "Reo Tahiti", 0, False),
"wa": ("Walloon", "Walon", 0, False),
"cy": ("Welsh", "Cymraeg", 0, False),
"wo": ("Wolof", "Wollof", 0, False),
"fy": ("Western Frisian", "Frysk", 0, False),
"xh": ("Xhosa", "isi Xhosa", 0, False),
"yo": ("Yoruba", "Yorùbá", 0, False),
"zu": ("Zulu", "isi Zulu", 0, False),
"zh_CN": ("SimpChinese", "简体中文", 936, False),
}
# Setup a safe null-translation

View File

@@ -837,27 +837,47 @@ def find_on_path(targets):
return None
def probablyipv4(ip):
def is_ipv4_addr(ip: str) -> bool:
""" Determine if the ip is an IPv4 address """
try:
return ipaddress.ip_address(ip).version == 4
except:
except ValueError:
return False
def probablyipv6(ip):
# Returns True if the given input is probably an IPv6 address
# Square Brackets like '[2001::1]' are OK
def is_ipv6_addr(ip: str) -> bool:
""" Determine if the ip is an IPv6 address; square brackets ([2001::1]) are OK """
try:
# Check for plain IPv6 address
return ipaddress.ip_address(ip).version == 6
except:
try:
# Remove '[' and ']' and test again:
ip = re.search(r"^\[(.*)\]$", ip).group(1)
return ipaddress.ip_address(ip).version == 6
except:
# No, not an IPv6 address
return False
return ipaddress.ip_address(ip.strip("[]")).version == 6
except (ValueError, AttributeError):
return False
def is_loopback_addr(ip: str) -> bool:
""" Determine if the ip is an IPv4 or IPv6 local loopback address """
try:
if ip.find(".") < 0:
ip = ip.strip("[]")
return ipaddress.ip_address(ip).is_loopback
except (ValueError, AttributeError):
return False
def is_localhost(value: str) -> bool:
""" Determine if the input is some variety of 'localhost' """
return (value == "localhost") or is_loopback_addr(value)
def is_lan_addr(ip: str) -> bool:
""" Determine if the ip is a local area network address """
try:
return (
ip not in ("0.0.0.0", "255.255.255.255", "::")
and ipaddress.ip_address(ip).is_private
and not is_loopback_addr(ip)
)
except ValueError:
return False
def ip_extract() -> List[str]:

View File

@@ -32,7 +32,7 @@ import sabnzbd
import sabnzbd.cfg
from sabnzbd.constants import DEF_TIMEOUT
from sabnzbd.encoding import utob
from sabnzbd.misc import nntp_to_msg, probablyipv4, probablyipv6, get_server_addrinfo
from sabnzbd.misc import nntp_to_msg, is_ipv4_addr, is_ipv6_addr, get_server_addrinfo
# Set pre-defined socket timeout
socket.setdefaulttimeout(DEF_TIMEOUT)
@@ -269,9 +269,9 @@ class NNTP:
af, socktype, proto, canonname, sa = self.nw.server.info[0]
# there will be a connect to host (or self.host, so let's force set 'af' to the correct value
if probablyipv4(self.host):
if is_ipv4_addr(self.host):
af = socket.AF_INET
if probablyipv6(self.host):
if is_ipv6_addr(self.host):
af = socket.AF_INET6
# Secured or unsecured?

View File

@@ -58,7 +58,7 @@ def nzbfile_parser(raw_data, nzo):
if meta_type not in nzo.meta:
nzo.meta[meta_type] = []
nzo.meta[meta_type].append(meta.text)
logging.debug("NZB Meta-data = %s", nzo.meta)
logging.debug("NZB file meta-data = %s", nzo.meta)
# Parse the files
for file in nzb_tree.iter("file"):

View File

@@ -170,21 +170,18 @@ class Article(TryList):
if not self.fetcher and not self.server_in_try_list(server):
if log:
logging.debug("Article %s | Server: %s | in second if", self.article, server.host)
# Is the current selected server of the same priority as this article?
if log:
# Is the current selected server of the same priority as this article?
logging.debug(
"Article %s | Server: %s | Article priority: %s", self.article, server.host, self.fetcher_priority
)
if log:
logging.debug(
"Article %s | Server: %s | Server priority: %s", self.article, server.host, server.priority
)
if server.priority == self.fetcher_priority:
if log:
logging.debug("Article %s | Server: %s | same priority, use it", self.article, server.host)
self.fetcher = server
self.tries += 1
if log:
logging.debug("Article %s | Server: %s | same priority, use it", self.article, server.host)
logging.debug("Article %s | Server: %s | Article-try: %s", self.article, server.host, self.tries)
return self
else:
@@ -904,6 +901,7 @@ class NzbObject(TryList):
for kw in self.meta:
if not self.nzo_info.get(kw):
self.nzo_info[kw] = self.meta[kw][0]
logging.debug("NZB nzo-info = %s", self.nzo_info)
# Show first meta-password (if any), when there's no explicit password
if not self.password and self.meta.get("password"):

View File

@@ -678,6 +678,8 @@ SKIN_TEXT = {
"addMultipleFeeds": TT("Seperate multiple URLs by a comma"), #: Config->RSS, placeholder (cannot be too long)
"button-preFeed": TT("Read Feed"), #: Config->RSS button
"button-forceFeed": TT("Force Download"), #: Config->RSS button
"rss-edit": TT("Edit"), #: Config->RSS edit button
"rss-nextscan": TT("Next scan at"), #: Config->RSS when will be the next RSS scan
"rss-order": TT("Order"), #: Config->RSS table column header
"rss-type": TT("Type"), #: Config->RSS table column header
"rss-filter": TT("Filter"), #: Config->RSS table column header

View File

@@ -5,5 +5,5 @@
# You MUST use double quotes (so " and not ')
__version__ = "3.2.0-develop"
__baseline__ = "unknown"
__version__ = "3.2.0"
__baseline__ = "7be9281431315ecfff806bb1d47106afbeca2e89"

View File

@@ -35,7 +35,7 @@ except:
import sabnzbd
import sabnzbd.cfg as cfg
from sabnzbd.constants import LOCALHOSTS
from sabnzbd.misc import is_localhost
_BONJOUR_OBJECT = None
@@ -58,7 +58,7 @@ def set_bonjour(host=None, port=None):
""" Publish host/port combo through Bonjour """
global _HOST_PORT, _BONJOUR_OBJECT
if not _HAVE_BONJOUR or not cfg.enable_bonjour():
if not _HAVE_BONJOUR or not cfg.enable_broadcast():
logging.info("No bonjour/zeroconf support installed")
return
@@ -71,8 +71,8 @@ def set_bonjour(host=None, port=None):
zhost = None
domain = None
if host in LOCALHOSTS:
logging.info("bonjour/zeroconf cannot be one of %s", LOCALHOSTS)
if is_localhost(host):
logging.info("Cannot setup bonjour/zeroconf for localhost (%s)", host)
# All implementations fail to implement "localhost" properly
# A false address is published even when scope==kDNSServiceInterfaceIndexLocalOnly
return

View File

@@ -21,7 +21,7 @@ tests.test_utils.test_check_dir - Testing SABnzbd checkdir util
from sabnzbd.cfg import selftest_host
from sabnzbd.getipaddress import *
from sabnzbd.misc import probablyipv4, probablyipv6
from sabnzbd.misc import is_ipv4_addr, is_ipv6_addr
class TestGetIpAddress:
@@ -33,14 +33,14 @@ class TestGetIpAddress:
def test_publicipv4(self):
public_ipv4 = publicipv4()
assert probablyipv4(public_ipv4)
assert is_ipv4_addr(public_ipv4)
def test_localipv4(self):
local_ipv4 = localipv4()
assert probablyipv4(local_ipv4)
assert is_ipv4_addr(local_ipv4)
def test_ipv6(self):
test_ipv6 = ipv6()
# Not all systems have IPv6
if test_ipv6:
assert probablyipv6(test_ipv6)
assert is_ipv6_addr(test_ipv6)

View File

@@ -230,6 +230,154 @@ class TestMisc:
# Make sure the output is cmd.exe-compatible
assert res == expected_output
@pytest.mark.parametrize(
"value, result",
[
("1.2.3.4", True),
("255.255.255.255", True),
("0.0.0.0", True),
("10.11.12.13", True),
("127.0.0.1", True),
("400.500.600.700", False),
("blabla", False),
("2001::1", False),
("::1", False),
("::", False),
("example.org", False),
(None, False),
("", False),
("3.2.0", False),
(-42, False),
],
)
def test_is_ipv4_addr(self, value, result):
assert misc.is_ipv4_addr(value) is result
@pytest.mark.parametrize(
"value, result",
[
("2001::1", True),
("::1", True),
("[2001::1]", True),
("fdd6:5a2d:3f20:0:14b0:d8f4:ccb9:fab6", True),
("::", True),
("a::b", True),
("1.2.3.4", False),
("255.255.255.255", False),
("0.0.0.0", False),
("10.11.12.13", False),
("127.0.0.1", False),
("400.500.600.700", False),
("blabla", False),
(666, False),
("example.org", False),
(None, False),
("", False),
("[1.2.3.4]", False),
("2001:1", False),
("2001::[2001::1]", False),
],
)
def test_is_ipv6_addr(self, value, result):
assert misc.is_ipv6_addr(value) is result
@pytest.mark.parametrize(
"value, result",
[
("::1", True),
("[::1]", True),
("127.0.0.1", True),
("127.255.0.0", True),
("127.1.2.7", True),
("fdd6:5a2d:3f20:0:14b0:d8f4:ccb9:fab6", False),
("::", False),
("a::b", False),
("1.2.3.4", False),
("255.255.255.255", False),
("0.0.0.0", False),
("10.11.12.13", False),
("400.500.600.700", False),
("localhost", False),
(-666, False),
("example.org", False),
(None, False),
("", False),
("[127.6.6.6]", False),
("2001:1", False),
("2001::[2001::1]", False),
],
)
def test_is_loopback_addr(self, value, result):
assert misc.is_loopback_addr(value) is result
@pytest.mark.parametrize(
"value, result",
[
("localhost", True),
("::1", True),
("[::1]", True),
("localhost", True),
("127.0.0.1", True),
("127.255.0.0", True),
("127.1.2.7", True),
(".local", False),
("test.local", False),
("fdd6:5a2d:3f20:0:14b0:d8f4:ccb9:fab6", False),
("::", False),
("a::b", False),
("1.2.3.4", False),
("255.255.255.255", False),
("0.0.0.0", False),
("10.11.12.13", False),
("400.500.600.700", False),
(-1984, False),
("example.org", False),
(None, False),
("", False),
("[127.6.6.6]", False),
("2001:1", False),
("2001::[2001::1]", False),
],
)
def test_is_localhost(self, value, result):
assert misc.is_localhost(value) is result
@pytest.mark.parametrize(
"value, result",
[
("10.11.12.13", True),
("172.16.2.81", True),
("192.168.255.255", True),
("169.254.42.42", True), # Link-local
("fd00::ffff", True), # Part of fc00::/7, IPv6 "Unique Local Addresses"
("fe80::a1", True), # IPv6 Link-local
("::1", False),
("localhost", False),
("127.0.0.1", False),
("2001:1337:babe::", False),
("172.32.32.32", False), # Near but not part of 172.16.0.0/12
("100.64.0.1", False), # Test net
("[2001::1]", False),
("::", False),
("::a:b:c", False),
("1.2.3.4", False),
("255.255.255.255", False),
("0.0.0.0", False),
("127.0.0.1", False),
("400.500.600.700", False),
("blabla", False),
(-666, False),
("example.org", False),
(None, False),
("", False),
("[1.2.3.4]", False),
("2001:1", False),
("2001::[2001::1]", False),
],
)
def test_is_lan_addr(self, value, result):
assert misc.is_lan_addr(value) is result
class TestBuildAndRunCommand:
# Path should exist

View File

@@ -1,46 +0,0 @@
#!/usr/bin/python3 -OO
# Copyright 2007-2021 The SABnzbd-Team <team@sabnzbd.org>
#
# This program is free software; you can redistribute it and/or
# modify it under the terms of the GNU General Public License
# as published by the Free Software Foundation; either version 2
# of the License, or (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program; if not, write to the Free Software
# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
"""
tests.test_utils.test_probablyip - Testing SABnzbd's probablyipX() functions
"""
from sabnzbd.misc import *
class TestProbablyIP:
def test_probablyipv4(self):
# Positive testing
assert probablyipv4("1.2.3.4")
assert probablyipv4("255.255.255.255")
assert probablyipv4("0.0.0.0")
# Negative testing
assert not probablyipv4("400.500.600.700")
assert not probablyipv4("blabla")
assert not probablyipv4("2001::1")
def test_probablyipv6(self):
# Positive testing
assert probablyipv6("2001::1")
assert probablyipv6("[2001::1]")
assert probablyipv6("fdd6:5a2d:3f20:0:14b0:d8f4:ccb9:fab6")
# Negative testing
assert not probablyipv6("blabla")
assert not probablyipv6("1.2.3.4")
assert not probablyipv6("[1.2.3.4]")
assert not probablyipv6("2001:1")
assert not probablyipv6("2001::[2001::1]")