mirror of
https://github.com/sabnzbd/sabnzbd.git
synced 2026-01-17 20:11:22 -05:00
Compare commits
89 Commits
3.2.0
...
3.3.0Beta2
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
e7dc81eb38 | ||
|
|
c2fa08598e | ||
|
|
d23ca4a38e | ||
|
|
078b608582 | ||
|
|
a64457973f | ||
|
|
00ef13fe9f | ||
|
|
b4a7f2fdf6 | ||
|
|
a482bb7acc | ||
|
|
ce46eeac49 | ||
|
|
110dbf6cca | ||
|
|
c93de2dd6f | ||
|
|
be88f5152f | ||
|
|
efda5bab4d | ||
|
|
d491eb1af0 | ||
|
|
e249dbfc67 | ||
|
|
c994ae5798 | ||
|
|
cba61bd8fb | ||
|
|
a72440ee6b | ||
|
|
cd3ed40ff3 | ||
|
|
cf3ce5e31d | ||
|
|
bdcbc5e011 | ||
|
|
c2d3ce348f | ||
|
|
970d580e4b | ||
|
|
d2f9721576 | ||
|
|
8a39e5827b | ||
|
|
89c8b6a0a5 | ||
|
|
238f0a6108 | ||
|
|
19950569cb | ||
|
|
a19553dddd | ||
|
|
c383a5b120 | ||
|
|
dab7243ccd | ||
|
|
ccf15ab4a3 | ||
|
|
25a3ef2b3e | ||
|
|
9bdaae8d9f | ||
|
|
4115651998 | ||
|
|
58349082df | ||
|
|
aa75828296 | ||
|
|
10eaf6e278 | ||
|
|
04e22571e9 | ||
|
|
bc8b9e7c8b | ||
|
|
b6213654ef | ||
|
|
9ba17d5338 | ||
|
|
dde453744d | ||
|
|
a86273f213 | ||
|
|
2b312dfa6f | ||
|
|
800c7182c1 | ||
|
|
cbbd5faf24 | ||
|
|
bb9c8f04e2 | ||
|
|
50469903dc | ||
|
|
b8f6cf11d6 | ||
|
|
f0d4f76e0f | ||
|
|
05f0a12d16 | ||
|
|
a1cad730ad | ||
|
|
3e8c738496 | ||
|
|
940dd3e3c0 | ||
|
|
6de4e1a401 | ||
|
|
0a8747f600 | ||
|
|
68a5e7c8f7 | ||
|
|
c3d4bf5428 | ||
|
|
0cac0bc761 | ||
|
|
05427b7b3b | ||
|
|
9e73f9b5e0 | ||
|
|
5ec41bafbe | ||
|
|
cb67cc8c3d | ||
|
|
d35619805f | ||
|
|
cb26758d53 | ||
|
|
9783674890 | ||
|
|
270eeda3e2 | ||
|
|
24d3d064bb | ||
|
|
e8eec80696 | ||
|
|
c366504868 | ||
|
|
c7b54856c5 | ||
|
|
10c56e08d4 | ||
|
|
4af51b4a76 | ||
|
|
65cc03da14 | ||
|
|
e908cb0df5 | ||
|
|
ae2cee3fda | ||
|
|
0467ed7ffc | ||
|
|
d5453b4aa4 | ||
|
|
7096a785db | ||
|
|
c80db13c28 | ||
|
|
b971045cd2 | ||
|
|
61d4ccbf1b | ||
|
|
c3b237466c | ||
|
|
29c727319d | ||
|
|
52c5dc589d | ||
|
|
35cad9bf22 | ||
|
|
b108876017 | ||
|
|
52bfff953a |
1
.github/workflows/black.yml
vendored
1
.github/workflows/black.yml
vendored
@@ -19,3 +19,4 @@ jobs:
|
||||
--line-length=120
|
||||
--target-version=py36
|
||||
--check
|
||||
--diff
|
||||
|
||||
8
.github/workflows/build_release.yml
vendored
8
.github/workflows/build_release.yml
vendored
@@ -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.4
|
||||
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
|
||||
3
.gitignore
vendored
3
.gitignore
vendored
@@ -31,6 +31,9 @@ SABnzbd-*/
|
||||
*.wp[ru]
|
||||
.idea
|
||||
|
||||
# VScode
|
||||
.vscode/
|
||||
|
||||
# Testing folders
|
||||
.cache
|
||||
.xprocess
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
SABnzbd 3.2.0
|
||||
SABnzbd 3.3.0
|
||||
|
||||
-------------------------------------------------------------------------------
|
||||
0) LICENSE
|
||||
|
||||
@@ -14,13 +14,13 @@
|
||||
For these the server blocking method is not very favourable.
|
||||
There is an INI-only option that will limit blocks to 1 minute.
|
||||
no_penalties = 1
|
||||
See: https://sabnzbd.org/wiki/configuration/3.2/special
|
||||
See: https://sabnzbd.org/wiki/configuration/3.3/special
|
||||
|
||||
- Some third-party utilties try to probe SABnzbd API in such a way that you will
|
||||
often see warnings about unauthenticated access.
|
||||
If you are sure these probes are harmless, you can suppress the warnings by
|
||||
setting the option "api_warnings" to 0.
|
||||
See: https://sabnzbd.org/wiki/configuration/3.2/special
|
||||
See: https://sabnzbd.org/wiki/configuration/3.3/special
|
||||
|
||||
- On macOS you may encounter downloaded files with foreign characters.
|
||||
The par2 repair may fail when the files were created on a Windows system.
|
||||
|
||||
4
PKG-INFO
4
PKG-INFO
@@ -1,7 +1,7 @@
|
||||
Metadata-Version: 1.0
|
||||
Name: SABnzbd
|
||||
Version: 3.2.0RC1
|
||||
Summary: SABnzbd-3.2.0RC1
|
||||
Version: 3.3.0Beta2
|
||||
Summary: SABnzbd-3.3.0Beta2
|
||||
Home-page: https://sabnzbd.org
|
||||
Author: The SABnzbd Team
|
||||
Author-email: team@sabnzbd.org
|
||||
|
||||
77
README.mkd
77
README.mkd
@@ -1,61 +1,30 @@
|
||||
Release Notes - SABnzbd 3.2.0 Release Candidate 1
|
||||
Release Notes - SABnzbd 3.3.0 Beta 2
|
||||
=========================================================
|
||||
|
||||
## 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
|
||||
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.
|
||||
- Increased garbage collection rate to reduce memory usage.
|
||||
- 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 `Minimum Free Space for Completed Download Folder` option.
|
||||
- Added option to `Auto resume` for both `Minimum Free Space` settings.
|
||||
- Multiple additional Queue and History columns can be added.
|
||||
- Added option to always use full screen width.
|
||||
- Additional interface settings can be stored server-side.
|
||||
- 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.
|
||||
- Program shutdown time reduced to almost instant.
|
||||
- Added `10 GB` test download.
|
||||
- IPv6 is no longer preferred in HappyEyeballs address selection.
|
||||
- API-calls `queue` and `history` can now be filtered by `nzo_id`.
|
||||
- Windows: `Temporary Download` job folders no longer have a maximum length.
|
||||
- Windows/macOS: Update UnRar to 6.0.0 and MultiPar to 1.3.1.3.
|
||||
## Changes since 3.3.0 Beta 1
|
||||
- Binaries would show an error when starting.
|
||||
|
||||
## Changes since 3.2.1
|
||||
- The `External internet access` will automatically detect local network
|
||||
and no longer requires the ranges to be defined. Custom ranges can still
|
||||
be defined through `local_ranges` in Special settings.
|
||||
- The `Unwanted extensions` detection can be set to `Whitelist`-mode.
|
||||
This will block or pause all jobs with non-matching extensions.
|
||||
- Servers article statistics are shown in K, G, M-notation.
|
||||
- Resolution added as a pattern key (`%r`) for Sorting.
|
||||
- Revised handling of categories, scripts, and priorities when adding NZB's.
|
||||
- Download statistics are also shown when no History is shown.
|
||||
- Confirm rename if Direct Unpack is active for the job.
|
||||
- Obfuscated-RAR detection will always be performed.
|
||||
- All requests will be logged, not just API calls.
|
||||
|
||||
## Bugfixes since 3.1.1
|
||||
- Memory could leak after jobs were removed from the queue.
|
||||
- The active browser URL is used during the wizard.
|
||||
- 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
|
||||
- Improved obfuscation detection for `Deobfuscate final filenames`.
|
||||
- Keep original priority of duplicate jobs.
|
||||
- Increase 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`.
|
||||
- Prevent repetition of unwanted extension warnings.
|
||||
- Correct notification category for failed URL fetches.
|
||||
- Improvements to the `Add NZB` modal window.
|
||||
- Sort script drop-down list alphabetically.
|
||||
- Default Bandwidth percentage was not set to `100`.
|
||||
- Direct Unpack stability fixes.
|
||||
- macOS: Program shutdown could fail.
|
||||
- macOS: Tray text was misaligned on macOS 11 (Big Sur).
|
||||
- Windows: Improved handling of some MultiPar output.
|
||||
- Windows: Program restart failed.
|
||||
- Prevent failed post-processing if job name ends in multiple dots or spaces.
|
||||
- Jobs could be stuck in the queue or duplicate if they had missing articles.
|
||||
- Login page could be accessed even if `External internet access` was set
|
||||
to `No access`. All other access would still be blocked.
|
||||
- Ignore duplicate files inside messy NZB's.
|
||||
- macOS: disk space would be incorrect for very large disks.
|
||||
|
||||
## Upgrade notices
|
||||
- The download statistics file `totals10.sab` is updated in this
|
||||
|
||||
91
SABnzbd.py
91
SABnzbd.py
@@ -19,7 +19,7 @@ import sys
|
||||
|
||||
if sys.hexversion < 0x03060000:
|
||||
print("Sorry, requires Python 3.6 or above")
|
||||
print("You can read more at: https://sabnzbd.org/python3")
|
||||
print("You can read more at: https://sabnzbd.org/wiki/installation/install-off-modules")
|
||||
sys.exit(1)
|
||||
|
||||
import logging
|
||||
@@ -48,7 +48,7 @@ try:
|
||||
except ImportError as e:
|
||||
print("Not all required Python modules are available, please check requirements.txt")
|
||||
print("Missing module:", e.name)
|
||||
print("You can read more at: https://sabnzbd.org/python3")
|
||||
print("You can read more at: https://sabnzbd.org/wiki/installation/install-off-modules")
|
||||
print("If you still experience problems, remove all .pyc files in this folder and subfolders")
|
||||
sys.exit(1)
|
||||
|
||||
@@ -68,7 +68,8 @@ from sabnzbd.misc import (
|
||||
get_serv_parms,
|
||||
get_from_url,
|
||||
upload_file_to_sabnzbd,
|
||||
probablyipv4,
|
||||
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
|
||||
@@ -135,16 +136,29 @@ class GUIHandler(logging.Handler):
|
||||
except TypeError:
|
||||
parsed_msg = record.msg + str(record.args)
|
||||
|
||||
if record.levelno == logging.WARNING:
|
||||
sabnzbd.notifier.send_notification(T("Warning"), parsed_msg, "warning")
|
||||
else:
|
||||
sabnzbd.notifier.send_notification(T("Error"), parsed_msg, "error")
|
||||
warning = {
|
||||
"type": record.levelname,
|
||||
"text": parsed_msg,
|
||||
"time": int(time.time()),
|
||||
"origin": "%s%d" % (record.filename, record.lineno),
|
||||
}
|
||||
|
||||
# Append traceback, if available
|
||||
warning = {"type": record.levelname, "text": parsed_msg, "time": int(time.time())}
|
||||
if record.exc_info:
|
||||
warning["text"] = "%s\n%s" % (warning["text"], traceback.format_exc())
|
||||
|
||||
# Do not notify the same notification within 1 minute from the same source
|
||||
# This prevents endless looping if the notification service itself throws an error/warning
|
||||
# We don't check based on message content, because if it includes a timestamp it's not unique
|
||||
if not any(
|
||||
stored_warning["origin"] == warning["origin"] and stored_warning["time"] + DEF_TIMEOUT > time.time()
|
||||
for stored_warning in self.store
|
||||
):
|
||||
if record.levelno == logging.WARNING:
|
||||
sabnzbd.notifier.send_notification(T("Warning"), parsed_msg, "warning")
|
||||
else:
|
||||
sabnzbd.notifier.send_notification(T("Error"), parsed_msg, "error")
|
||||
|
||||
# Loose the oldest record
|
||||
if len(self.store) >= self._size:
|
||||
self.store.pop(0)
|
||||
@@ -533,7 +547,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 +614,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 +1503,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
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
# Basic build requirements
|
||||
pyinstaller
|
||||
pyinstaller==4.2
|
||||
setuptools
|
||||
pkginfo
|
||||
certifi
|
||||
|
||||
@@ -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')
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
<!--#set global $pane="Config"#-->
|
||||
<!--#set global $help_uri="configuration/3.2/configure"#-->
|
||||
<!--#set global $help_uri="configuration/3.3/configure"#-->
|
||||
<!--#include $webdir + "/_inc_header_uc.tmpl"#-->
|
||||
|
||||
<!--#from sabnzbd.encoding import CODEPAGE#-->
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
<!--#set global $pane="Categories"#-->
|
||||
<!--#set global $help_uri="configuration/3.2/categories"#-->
|
||||
<!--#set global $help_uri="configuration/3.3/categories"#-->
|
||||
<!--#include $webdir + "/_inc_header_uc.tmpl"#-->
|
||||
<div class="colmask">
|
||||
<div class="section">
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
<!--#set global $pane="Folders"#-->
|
||||
<!--#set global $help_uri="configuration/3.2/folders"#-->
|
||||
<!--#set global $help_uri="configuration/3.3/folders"#-->
|
||||
<!--#include $webdir + "/_inc_header_uc.tmpl"#-->
|
||||
|
||||
<div class="colmask">
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
<!--#set global $pane="General"#-->
|
||||
<!--#set global $help_uri="configuration/3.2/general"#-->
|
||||
<!--#set global $help_uri="configuration/3.3/general"#-->
|
||||
<!--#include $webdir + "/_inc_header_uc.tmpl"#-->
|
||||
|
||||
<div class="colmask">
|
||||
@@ -131,12 +131,7 @@
|
||||
<option value="5" <!--#if $inet_exposure == 5 then 'selected="selected"' else ""#-->>$T('inet-ui') - $T('inet-external_login')</option>
|
||||
</optgroup>
|
||||
</select>
|
||||
<span class="desc">$T('explain-inet_exposure').replace('. ','.<br><span class="label label-warning">'+$T('warning').upper()+'</span> ')</span>
|
||||
</div>
|
||||
<div class="field-pair">
|
||||
<label class="config" for="local_ranges">$T('opt-local_ranges')</label>
|
||||
<input type="text" name="local_ranges" id="local_ranges" value="$local_ranges" />
|
||||
<span class="desc">$T('explain-local_ranges')</span>
|
||||
<span class="desc">$T('explain-inet_exposure')</span>
|
||||
</div>
|
||||
<div class="field-pair">
|
||||
<label class="config" for="apikey_display">$T('opt-apikey')</label>
|
||||
@@ -260,17 +255,18 @@
|
||||
|
||||
// Highlight in case user is not safe
|
||||
// So when exposed to internet and no password, no external limit or no username/password
|
||||
var safeCheck = \$('#host, #local_ranges, #inet_exposure, #${pid}_wu, #${pid}_wp')
|
||||
var safeCheck = \$('#host, #inet_exposure, #${pid}_wu, #${pid}_wp')
|
||||
function checkSafety() {
|
||||
if(\$('#host').val() != 'localhost' && \$('#host').val() != '127.0.0.1') {
|
||||
// No limitation on local-network
|
||||
if(!\$('#local_ranges').val() || \$('#inet_exposure').val() > 3) {
|
||||
if(\$('#inet_exposure').val() > 3) {
|
||||
// And no username and password?
|
||||
if(!\$('#${pid}_wu').val() || !\$('#${pid}_wp').val()) {
|
||||
// Add warning icon if not there already
|
||||
if(!\$('.host-warning').length) {
|
||||
safeCheck.after('<span class="glyphicon glyphicon-alert host-warning"></span>')
|
||||
\$('.host-warning').tooltip({'title': '$T('checkSafety')'})
|
||||
safeCheck.addClass('host-warning-highlight')
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
<!--#set global $pane="Email"#-->
|
||||
<!--#set global $help_uri="configuration/3.2/notifications"#-->
|
||||
<!--#set global $help_uri="configuration/3.3/notifications"#-->
|
||||
<!--#include $webdir + "/_inc_header_uc.tmpl"#-->
|
||||
|
||||
<!--#def show_notify_checkboxes($section_label)#-->
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
<!--#set global $pane="RSS"#-->
|
||||
<!--#set global $help_uri="configuration/3.2/rss"#-->
|
||||
<!--#set global $help_uri="configuration/3.3/rss"#-->
|
||||
<!--#include $webdir + "/_inc_header_uc.tmpl"#-->
|
||||
<!--#import html#-->
|
||||
<div class="colmask">
|
||||
@@ -10,7 +10,7 @@
|
||||
<p>$T('explain-RSS')</p>
|
||||
<form action="add_rss_feed" method="post" autocomplete="off">
|
||||
<input type="hidden" name="apikey" value="$apikey" />
|
||||
<table class="catTable">
|
||||
<table class="catTable addRssTable">
|
||||
<tr>
|
||||
<th> </th>
|
||||
<th>$T('name')</th>
|
||||
@@ -21,10 +21,10 @@
|
||||
<td>
|
||||
<input type="checkbox" name="enable" value="1" checked />
|
||||
</td>
|
||||
<td>
|
||||
<input type="text" name="feed" class="smaller_input" value="$feed" />
|
||||
<td class="new-feed-title">
|
||||
<input type="text" name="feed" value="$feed" />
|
||||
</td>
|
||||
<td>
|
||||
<td class="new-feed-url">
|
||||
<input type="text" name="uri" placeholder="$T('addMultipleFeeds')" />
|
||||
</td>
|
||||
<td class="nowrap">
|
||||
@@ -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"> $T('Next scan at:') $rss_next</span>
|
||||
<span class="config narrow"> $T('rss-nextscan'): $rss_next</span>
|
||||
<span class="desc narrow">$T('explain-rss_rate')</span>
|
||||
</div>
|
||||
</fieldset>
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
<!--#set global $pane="Scheduling"#-->
|
||||
<!--#set global $help_uri="configuration/3.2/scheduling"#-->
|
||||
<!--#set global $help_uri="configuration/3.3/scheduling"#-->
|
||||
<!--#include $webdir + "/_inc_header_uc.tmpl"#-->
|
||||
|
||||
<%
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
<!--#set global $pane="Servers"#-->
|
||||
<!--#set global $help_uri="configuration/3.2/servers"#-->
|
||||
<!--#set global $help_uri="configuration/3.3/servers"#-->
|
||||
<!--#include $webdir + "/_inc_header_uc.tmpl"#-->
|
||||
|
||||
<!--#import json#-->
|
||||
@@ -144,7 +144,7 @@
|
||||
|
||||
<div class="section <!--#if int($server['enable']) == 0 then 'server-disabled' else ""#-->">
|
||||
<div class="col2 <!--#if int($server['enable']) == 0 then 'server-disabled' else ""#-->">
|
||||
<h3>$server['displayname'] <a href="$helpuri$help_uri" target="_blank"><span class="glyphicon glyphicon-question-sign"></span></a></h3>
|
||||
<h3 title="$server['displayname']">$server['displayname'] <a href="$helpuri$help_uri" target="_blank"><span class="glyphicon glyphicon-question-sign"></span></a></h3>
|
||||
<!--#if int($server['enable']) != 0 #-->
|
||||
<!--#if $last_prio != $server['priority'] and $cur_prio_color+1 < len($prio_colors) #-->
|
||||
<!--#set $cur_prio_color = $cur_prio_color+1 #-->
|
||||
@@ -273,6 +273,9 @@
|
||||
<b>$T('srv-article-availability'):</b><br/>
|
||||
$T('selectedDates'): <span id="server-article-value-${cur}"></span>
|
||||
</p>
|
||||
<!--#if $server['expire_date']#-->
|
||||
<p><b>$T('srv-expire_date'):</b> $(server['expire_date'])</p>
|
||||
<!--#end if#-->
|
||||
<!--#if $server['quota']#-->
|
||||
<p><b>$T('quota-left'):</b> $(server['quota_left'])B</p>
|
||||
<!--#end if#-->
|
||||
@@ -385,7 +388,8 @@
|
||||
|
||||
// If values were missing
|
||||
if(!isNaN(articleRatio)) {
|
||||
\$('#server-article-value-' + server_id).text('$T("srv-articles-tried")'.replace('%f', articleRatio).replace('%d', totalArticlesTriedThisRange))
|
||||
// Use filesize to convert to unit-display
|
||||
\$('#server-article-value-' + server_id).text('$T("srv-articles-tried")'.replace('%f', articleRatio).replace('%d', filesize(totalArticlesTriedThisRange, {unix: true, round: 0, spacer: "", base: 1})))
|
||||
} else {
|
||||
\$('#server-article-value-' + server_id).text('$T("notAvailable")')
|
||||
}
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
<!--#set global $pane="Sorting"#-->
|
||||
<!--#set global $help_uri="configuration/3.2/sorting"#-->
|
||||
<!--#set global $help_uri="configuration/3.3/sorting"#-->
|
||||
<!--#include $webdir + "/_inc_header_uc.tmpl"#-->
|
||||
|
||||
<div class="colmask">
|
||||
@@ -130,6 +130,11 @@
|
||||
<td>%e_n</td>
|
||||
<td>$T('ep-us-name')</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td class="align-right"><b>$T('Resolution'):</b></td>
|
||||
<td>%r</td>
|
||||
<td>1080p</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td class="align-right"><b>$T('fileExt'):</b></td>
|
||||
<td>%ext</td>
|
||||
@@ -245,6 +250,11 @@
|
||||
<td>%y</td>
|
||||
<td>2009</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td class="align-right"><b>$T('Resolution'):</b></td>
|
||||
<td>%r</td>
|
||||
<td>1080p</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td class="align-right"><b>$T('extension'):</b></td>
|
||||
<td>%ext</td>
|
||||
@@ -407,6 +417,11 @@
|
||||
<td>%0decade</td>
|
||||
<td>2000</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td class="align-right"><b>$T('Resolution'):</b></td>
|
||||
<td>%r</td>
|
||||
<td>1080p</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td class="align-right"><b>$T('orgFilename'):</b></td>
|
||||
<td>%fn</td>
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
<!--#set global $pane="Special"#-->
|
||||
<!--#set global $help_uri="configuration/3.2/special"#-->
|
||||
<!--#set global $help_uri="configuration/3.3/special"#-->
|
||||
<!--#include $webdir + "/_inc_header_uc.tmpl"#-->
|
||||
|
||||
<div class="colmask">
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
<!--#set global $pane="Switches"#-->
|
||||
<!--#set global $help_uri="configuration/3.2/switches"#-->
|
||||
<!--#set global $help_uri="configuration/3.3/switches"#-->
|
||||
<!--#include $webdir + "/_inc_header_uc.tmpl"#-->
|
||||
|
||||
<div class="colmask">
|
||||
@@ -120,6 +120,10 @@
|
||||
</div>
|
||||
<div class="field-pair">
|
||||
<label class="config" for="unwanted_extensions">$T('opt-unwanted_extensions')</label>
|
||||
<select name="unwanted_extensions_mode" id="unwanted_extensions_mode">
|
||||
<option value="0" <!--#if int($unwanted_extensions_mode) == 0 then 'selected="selected"' else ""#--> >$T('unwanted_extensions_blacklist')</option>
|
||||
<option value="1" <!--#if int($unwanted_extensions_mode) == 1 then 'selected="selected"' else ""#--> >$T('unwanted_extensions_whitelist')</option>
|
||||
</select>
|
||||
<input type="text" name="unwanted_extensions" id="unwanted_extensions" value="$unwanted_extensions"/>
|
||||
<span class="desc">$T('explain-unwanted_extensions')</span>
|
||||
</div>
|
||||
@@ -136,8 +140,8 @@
|
||||
<label class="config" for="auto_sort">$T('opt-auto_sort')</label>
|
||||
<select name="auto_sort" id="auto_sort">
|
||||
<option value="">$T('default')</option>
|
||||
<option value="avg_age asc" <!--#if $auto_sort == "avg_age asc" then 'selected="selected"' else ""#--> >$T('Glitter-sortAgeAsc')</option>
|
||||
<option value="avg_age desc" <!--#if $auto_sort == "avg_age desc" then 'selected="selected"' else ""#--> >$T('Glitter-sortAgeDesc')</option>
|
||||
<option value="avg_age desc" <!--#if $auto_sort == "avg_age desc" then 'selected="selected"' else ""#--> >$T('Glitter-sortAgeAsc')</option>
|
||||
<option value="avg_age asc" <!--#if $auto_sort == "avg_age asc" then 'selected="selected"' else ""#--> >$T('Glitter-sortAgeDesc')</option>
|
||||
<option value="name asc" <!--#if $auto_sort == "name asc" then 'selected="selected"' else ""#--> >$T('Glitter-sortNameAsc')</option>
|
||||
<option value="name desc" <!--#if $auto_sort == "name desc" then 'selected="selected"' else ""#--> >$T('Glitter-sortNameDesc')</option>
|
||||
<option value="size asc" <!--#if $auto_sort == "size asc" then 'selected="selected"' else ""#--> >$T('Glitter-sortSizeAsc')</option>
|
||||
|
||||
File diff suppressed because one or more lines are too long
@@ -550,6 +550,16 @@ tr.separator {
|
||||
padding-right: 13px;
|
||||
}
|
||||
/* -- */
|
||||
.RSS .addRssTable,
|
||||
.RSS .addRssTable input[type="text"] {
|
||||
width: 100%;
|
||||
}
|
||||
.RSS .addRssTable .new-feed-title {
|
||||
max-width: 250px;
|
||||
}
|
||||
.RSS .addRssTable .new-feed-url {
|
||||
width: 70%;
|
||||
}
|
||||
h2.activeRSS {
|
||||
margin-bottom: 10px;
|
||||
}
|
||||
@@ -559,12 +569,12 @@ h2.activeRSS {
|
||||
text-decoration: underline !important;
|
||||
}
|
||||
.favicon {
|
||||
background-position: center center!important;
|
||||
background-size: 16px 16px;
|
||||
background-position: center center !important;
|
||||
background-size: 22px 22px;
|
||||
opacity: 1;
|
||||
top: -1px;
|
||||
height: 16px;
|
||||
width: 16px;
|
||||
height: 22px;
|
||||
width: 22px;
|
||||
float: left;
|
||||
margin: 0 6px 0 2px;
|
||||
text-align: center;
|
||||
@@ -584,6 +594,7 @@ h2.activeRSS {
|
||||
}
|
||||
#subscriptions {
|
||||
border: 1px solid #E5E5E5;
|
||||
width: 100%;
|
||||
}
|
||||
.data-row {
|
||||
border-top: 1px solid #E5E5E5;
|
||||
@@ -595,6 +606,7 @@ h2.activeRSS {
|
||||
#subscriptions .chk {
|
||||
padding: 8px 5px 5px;
|
||||
vertical-align: middle;
|
||||
width: 40px;
|
||||
}
|
||||
#subscriptions .title {
|
||||
font-weight: bold;
|
||||
@@ -602,10 +614,11 @@ h2.activeRSS {
|
||||
width: auto;
|
||||
}
|
||||
#subscriptions .favicon {
|
||||
margin-left: 8px;
|
||||
margin-left: 7px;
|
||||
margin-top: -2px;
|
||||
}
|
||||
.ie6 .subscription-title {
|
||||
width: 20em;
|
||||
#subscriptions .glyphicon {
|
||||
margin-top: 3px;
|
||||
}
|
||||
.subscription-title,
|
||||
.subscription-title:hover {
|
||||
@@ -1090,6 +1103,10 @@ input[type="checkbox"] {
|
||||
font-size: 1.2em;
|
||||
}
|
||||
|
||||
.host-warning-highlight {
|
||||
border-color: #F0AD4E !important;
|
||||
}
|
||||
|
||||
.fileBrowser .glyphicon {
|
||||
margin-right: 2px;
|
||||
top: 1px;
|
||||
@@ -1168,6 +1185,31 @@ 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"] .field-pair {
|
||||
position: relative;
|
||||
}
|
||||
|
||||
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;
|
||||
|
||||
@@ -224,4 +224,10 @@
|
||||
<span data-bind="text: history.downloadedMonth"></span>B $T('Glitter-thisMonth')
|
||||
<span data-bind="text: history.downloadedTotal"></span>B $T('Glitter-total')
|
||||
</div>
|
||||
</div>
|
||||
<div class="info-container history-info" data-bind="visible: !hasHistory() && !displayTabbed()" style="display: none">
|
||||
<span class="glyphicon glyphicon-save"></span>
|
||||
<span data-bind="text: history.downloadedToday"></span>B $T('Glitter-today')
|
||||
<span data-bind="text: history.downloadedMonth"></span>B $T('Glitter-thisMonth')
|
||||
<span data-bind="text: history.downloadedTotal"></span>B $T('Glitter-total')
|
||||
</div>
|
||||
@@ -86,34 +86,34 @@
|
||||
<div class="tab-content">
|
||||
<div class="tab-pane fade in active" id="options-status">
|
||||
<div class="row">
|
||||
<div class="col-sm-6">$T('dashboard-localIP4')</div>
|
||||
<div class="col-sm-6">$T('dashboard-localIP4') </div>
|
||||
<div class="col-sm-6" data-bind="visible: hasStatusInfo, text: !statusInfo.localipv4() ? '$T('dashboard-connectionError')' : statusInfo.localipv4(), css: { 'options-bad-status' : !statusInfo.localipv4() }"></div>
|
||||
<div class="col-sm-6 col-loading" data-bind="visible: !hasStatusInfo()">$T('Glitter-loading')<span class="loader-dot-one">.</span><span class="loader-dot-two">.</span><span class="loader-dot-three">.</span></div>
|
||||
</div>
|
||||
<div class="row">
|
||||
<div class="col-sm-6">$T('dashboard-publicIP4')</div>
|
||||
<div class="col-sm-6">$T('dashboard-publicIP4') </div>
|
||||
<div class="col-sm-6" data-bind="visible: hasStatusInfo, text: !statusInfo.publicipv4() ? '$T('dashboard-connectionError')' : statusInfo.publicipv4(), css: { 'options-bad-status ' : !statusInfo.publicipv4() }"></div>
|
||||
<div class="col-sm-6 col-loading" data-bind="visible: !hasStatusInfo()">$T('Glitter-loading')<span class="loader-dot-one">.</span><span class="loader-dot-two">.</span><span class="loader-dot-three">.</span></div>
|
||||
</div>
|
||||
<div class="row">
|
||||
<div class="col-sm-6">$T('dashboard-IP6')</div>
|
||||
<div class="col-sm-6">$T('dashboard-IP6') </div>
|
||||
<div class="col-sm-6" data-bind="visible: hasStatusInfo, text: statusInfo.ipv6"></div>
|
||||
<div class="col-sm-6 col-loading" data-bind="visible: !hasStatusInfo()">$T('Glitter-loading')<span class="loader-dot-one">.</span><span class="loader-dot-two">.</span><span class="loader-dot-three">.</span></div>
|
||||
</div>
|
||||
<div class="row">
|
||||
<div class="col-sm-6">$T('dashboard-NameserverDNS')</div>
|
||||
<div class="col-sm-6">$T('dashboard-NameserverDNS') </div>
|
||||
<div class="col-sm-6" data-bind="visible: hasStatusInfo, text: !statusInfo.dnslookup() ? '$T('dashboard-connectionError')' : statusInfo.dnslookup(), css: { 'options-bad-status' : (statusInfo.dnslookup() != 'OK') }"></div>
|
||||
<div class="col-sm-6 col-loading" data-bind="visible: !hasStatusInfo()">$T('Glitter-loading')<span class="loader-dot-one">.</span><span class="loader-dot-two">.</span><span class="loader-dot-three">.</span></div>
|
||||
</div>
|
||||
<hr/>
|
||||
<div class="row">
|
||||
<div class="col-sm-6">$T('cache')</div>
|
||||
<div class="col-sm-6">$T('cache') </div>
|
||||
<div class="col-sm-6">
|
||||
<span data-bind="text: cacheSize"></span> (<span data-bind="text: cacheArticles"></span> $T('Glitter-articles'))
|
||||
</div>
|
||||
</div>
|
||||
<div class="row">
|
||||
<div class="col-sm-6">$T('dashboard-systemPerformance')</div>
|
||||
<div class="col-sm-6">$T('dashboard-systemPerformance') </div>
|
||||
<div class="col-sm-6" data-bind="visible: hasPerformanceInfo">
|
||||
<span data-bind="text: statusInfo.pystone"></span>
|
||||
<a href="#" data-bind="click: testDiskSpeed" data-tooltip="true" data-placement="right" title="$T('dashboard-repeatTest')"><span class="glyphicon glyphicon-repeat"></span></a>
|
||||
@@ -122,7 +122,7 @@
|
||||
<div class="col-sm-6 col-loading" data-bind="visible: !hasPerformanceInfo()">$T('Glitter-loading')<span class="loader-dot-one">.</span><span class="loader-dot-two">.</span><span class="loader-dot-three">.</span></div>
|
||||
</div>
|
||||
<div class="row">
|
||||
<div class="col-sm-6">$T('dashboard-downloadDirSpeed')</div>
|
||||
<div class="col-sm-6">$T('dashboard-downloadDirSpeed') </div>
|
||||
<div class="col-sm-6" data-bind="visible: hasPerformanceInfo">
|
||||
<span data-bind="text: statusInfo.downloaddirspeed()"></span> MB/s
|
||||
<a href="#" class="diskspeed-button" data-bind="click: testDiskSpeed" data-tooltip="true" data-placement="right" title="$T('dashboard-repeatTest')"><span class="glyphicon glyphicon-repeat"></span></a>
|
||||
@@ -131,7 +131,7 @@
|
||||
<div class="col-sm-6 col-loading" data-bind="visible: !hasPerformanceInfo()">$T('Glitter-loading')<span class="loader-dot-one">.</span><span class="loader-dot-two">.</span><span class="loader-dot-three">.</span></div>
|
||||
</div>
|
||||
<div class="row">
|
||||
<div class="col-sm-6">$T('dashboard-completeDirSpeed')</div>
|
||||
<div class="col-sm-6">$T('dashboard-completeDirSpeed') </div>
|
||||
<div class="col-sm-6" data-bind="visible: hasPerformanceInfo">
|
||||
<span data-bind="text: statusInfo.completedirspeed()"></span> MB/s
|
||||
<a href="#" class="diskspeed-button" data-bind="click: testDiskSpeed" data-tooltip="true" data-placement="right" title="$T('dashboard-repeatTest')"><span class="glyphicon glyphicon-repeat"></span></a>
|
||||
@@ -140,7 +140,7 @@
|
||||
<div class="col-sm-6 col-loading" data-bind="visible: !hasPerformanceInfo()">$T('Glitter-loading')<span class="loader-dot-one">.</span><span class="loader-dot-two">.</span><span class="loader-dot-three">.</span></div>
|
||||
</div>
|
||||
<div class="row">
|
||||
<div class="col-sm-6">$T('dashboard-internetBandwidth')</div>
|
||||
<div class="col-sm-6">$T('dashboard-internetBandwidth') </div>
|
||||
<div class="col-sm-6" data-bind="visible: hasPerformanceInfo">
|
||||
<span data-bind="text: statusInfo.internetbandwidth()"></span> MB/s
|
||||
<a href="#" class="diskspeed-button" data-bind="click: testDiskSpeed" data-tooltip="true" data-placement="right" title="$T('dashboard-repeatTest')"><span class="glyphicon glyphicon-repeat"></span></a>
|
||||
@@ -149,7 +149,7 @@
|
||||
<div class="col-sm-6 col-loading" data-bind="visible: !hasPerformanceInfo()">$T('Glitter-loading')<span class="loader-dot-one">.</span><span class="loader-dot-two">.</span><span class="loader-dot-three">.</span></div>
|
||||
</div>
|
||||
<div class="row test-download">
|
||||
<div class="col-sm-6">$T('dashboard-testDownload')</div>
|
||||
<div class="col-sm-6">$T('dashboard-testDownload') </div>
|
||||
<div class="col-sm-6">
|
||||
<a href="#" class="btn btn-default" data-bind="click: testDownload" data-size="100MB" data-tooltip="true" data-placement="top" title="$T('dashboard-testDownload-explain')"><span class="glyphicon glyphicon-download-alt"></span> 100 MB</a>
|
||||
<a href="#" class="btn btn-default" data-bind="click: testDownload" data-size="1000MB" data-tooltip="true" data-placement="top" title="$T('dashboard-testDownload-explain')"><span class="glyphicon glyphicon-download-alt"></span> 1 GB</a>
|
||||
|
||||
@@ -109,7 +109,7 @@
|
||||
<form data-bind="submit: editingNameSubmit">
|
||||
<input type="text" data-bind="value: nameForEdit, visible: editingName(), hasfocus: editingName" />
|
||||
</form>
|
||||
<div class="name-icons direct-unpack hover-button" data-bind="visible: direct_unpack">
|
||||
<div class="name-icons direct-unpack hover-button" data-bind="visible: direct_unpack() && !editingName()">
|
||||
<span class="glyphicon glyphicon-compressed"></span> <span data-bind="text: direct_unpack"></span>
|
||||
</div>
|
||||
<div class="name-options" data-bind="visible: !editingName(), css: { disabled: isGrabbing() }">
|
||||
|
||||
@@ -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#-->
|
||||
|
||||
@@ -52,15 +52,17 @@
|
||||
var glitterTranslate = new Object();
|
||||
glitterTranslate.paused = "$T('post-Paused')";
|
||||
glitterTranslate.left = "$T('Glitter-left')";
|
||||
glitterTranslate.clearWarn = "$T('Glitter-confirmClearWarnings')";
|
||||
glitterTranslate.clearWarn = "$T('confirm')";
|
||||
glitterTranslate.pausePromptFail = "$T('Glitter-pausePromptFail')"
|
||||
glitterTranslate.pauseFor = "$T('pauseFor')"
|
||||
glitterTranslate.minutes = "$T('mins')"
|
||||
glitterTranslate.shutdown = "$T('shutdownOK?')";
|
||||
glitterTranslate.restart = "$T('explain-Restart') $T('explain-needNewLogin')".replace(/\<br(\s*\/|)\>/g, '\n');
|
||||
glitterTranslate.repair = "$T('explain-Repair')".replace(/<br \/>/g, "\n").replace(/"/g,'"');
|
||||
glitterTranslate.removeDown = "$T('Glitter-confirmClearDownloads')";
|
||||
glitterTranslate.removeDow1 = "$T('Glitter-confirmClear1Download')";
|
||||
glitterTranslate.deleteMsg = "$T('nzo-delete')";
|
||||
glitterTranslate.removeDown = "$T('confirm')";
|
||||
glitterTranslate.removeDow1 = "$T('confirm')";
|
||||
glitterTranslate.renameAbort = "$T('Glitter-confirmAbortDirectUnpack')\n$T('confirm')";
|
||||
glitterTranslate.retryAll = "$T('link-retryAll')?";
|
||||
glitterTranslate.fetch = "$T('Glitter-fetch')";
|
||||
glitterTranslate.encrypted = "$T('Glitter-encrypted')";
|
||||
|
||||
@@ -421,7 +421,7 @@ function HistoryModel(parent, data) {
|
||||
// Delete button
|
||||
self.deleteSlot = function(item, event) {
|
||||
// Confirm?
|
||||
if(!self.parent.parent.confirmDeleteHistory() || confirm(glitterTranslate.removeDow1)) {
|
||||
if(!self.parent.parent.confirmDeleteHistory() || confirm(glitterTranslate.deleteMsg + ":\n" + item.historyStatus.name() + "\n\n" + glitterTranslate.removeDow1)) {
|
||||
// Are we still processing and it can be stopped?
|
||||
if(item.processingDownload() == 2) {
|
||||
callAPI({
|
||||
|
||||
@@ -652,6 +652,9 @@ function QueueModel(parent, data) {
|
||||
// Anything change or empty?
|
||||
if(!newName || self.name() == newName) return;
|
||||
|
||||
// Rename would abort Direct Unpack, so ask if user is sure
|
||||
if(self.direct_unpack() && !confirm(glitterTranslate.renameAbort)) return;
|
||||
|
||||
// Send rename
|
||||
callAPI({
|
||||
mode: 'queue',
|
||||
@@ -724,7 +727,7 @@ function QueueModel(parent, data) {
|
||||
// Remove 1 download from queue
|
||||
self.removeDownload = function(item, event) {
|
||||
// Confirm and remove
|
||||
if(!self.parent.parent.confirmDeleteQueue() || confirm(glitterTranslate.removeDow1)) {
|
||||
if(!self.parent.parent.confirmDeleteQueue() || confirm(glitterTranslate.deleteMsg + ":\n" + item.name() + "\n\n" + glitterTranslate.removeDow1)) {
|
||||
var itemToDelete = this;
|
||||
|
||||
// Show notification
|
||||
|
||||
@@ -0,0 +1 @@
|
||||
@import url('Night.css') screen and (prefers-color-scheme: dark);
|
||||
@@ -55,6 +55,10 @@ legend,
|
||||
opacity: 0.7;
|
||||
}
|
||||
|
||||
.form-control[disabled] {
|
||||
opacity: 0.65;
|
||||
}
|
||||
|
||||
.progress {
|
||||
background-color: #DADADA;
|
||||
}
|
||||
@@ -126,6 +130,10 @@ select.form-control,
|
||||
.main-content .btn-default,
|
||||
.modal-body .btn-default,
|
||||
.modal-footer .btn-default,
|
||||
.btn-default.disabled:hover,
|
||||
.btn-default.disabled:active,
|
||||
.btn-default.disabled:focus,
|
||||
.form-control[disabled],
|
||||
#modal-options .options-function-box .input-group-addon {
|
||||
background-color: #555555;
|
||||
color: #EBEBEB;
|
||||
@@ -157,6 +165,8 @@ tbody>tr:last-child td,
|
||||
input,
|
||||
input.form-control,
|
||||
.input-group-addon,
|
||||
.search-box input:focus,
|
||||
.search-box input:valid,
|
||||
select.form-control,
|
||||
#modal-options .table-server-connections th,
|
||||
.main-content .btn-default,
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -5,7 +5,7 @@
|
||||
#
|
||||
msgid ""
|
||||
msgstr ""
|
||||
"Project-Id-Version: SABnzbd-3.2.0-develop\n"
|
||||
"Project-Id-Version: SABnzbd-3.3.0-develop\n"
|
||||
"PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n"
|
||||
"Last-Translator: team@sabnzbd.org\n"
|
||||
"Language-Team: SABnzbd <team@sabnzbd.org>\n"
|
||||
|
||||
@@ -4,7 +4,7 @@
|
||||
#
|
||||
msgid ""
|
||||
msgstr ""
|
||||
"Project-Id-Version: SABnzbd-3.2.0-develop\n"
|
||||
"Project-Id-Version: SABnzbd-3.3.0-develop\n"
|
||||
"PO-Revision-Date: 2020-06-27 15:56+0000\n"
|
||||
"Language-Team: Czech (https://www.transifex.com/sabnzbd/teams/111101/cs/)\n"
|
||||
"MIME-Version: 1.0\n"
|
||||
|
||||
@@ -7,7 +7,7 @@
|
||||
#
|
||||
msgid ""
|
||||
msgstr ""
|
||||
"Project-Id-Version: SABnzbd-3.2.0-develop\n"
|
||||
"Project-Id-Version: SABnzbd-3.3.0-develop\n"
|
||||
"PO-Revision-Date: 2020-06-27 15:56+0000\n"
|
||||
"Last-Translator: Safihre <safihre@sabnzbd.org>, 2020\n"
|
||||
"Language-Team: Danish (https://www.transifex.com/sabnzbd/teams/111101/da/)\n"
|
||||
|
||||
@@ -7,7 +7,7 @@
|
||||
#
|
||||
msgid ""
|
||||
msgstr ""
|
||||
"Project-Id-Version: SABnzbd-3.2.0-develop\n"
|
||||
"Project-Id-Version: SABnzbd-3.3.0-develop\n"
|
||||
"PO-Revision-Date: 2020-06-27 15:56+0000\n"
|
||||
"Last-Translator: Safihre <safihre@sabnzbd.org>, 2020\n"
|
||||
"Language-Team: German (https://www.transifex.com/sabnzbd/teams/111101/de/)\n"
|
||||
|
||||
@@ -7,7 +7,7 @@
|
||||
#
|
||||
msgid ""
|
||||
msgstr ""
|
||||
"Project-Id-Version: SABnzbd-3.2.0-develop\n"
|
||||
"Project-Id-Version: SABnzbd-3.3.0-develop\n"
|
||||
"PO-Revision-Date: 2020-06-27 15:56+0000\n"
|
||||
"Last-Translator: Safihre <safihre@sabnzbd.org>, 2020\n"
|
||||
"Language-Team: Spanish (https://www.transifex.com/sabnzbd/teams/111101/es/)\n"
|
||||
|
||||
@@ -7,7 +7,7 @@
|
||||
#
|
||||
msgid ""
|
||||
msgstr ""
|
||||
"Project-Id-Version: SABnzbd-3.2.0-develop\n"
|
||||
"Project-Id-Version: SABnzbd-3.3.0-develop\n"
|
||||
"PO-Revision-Date: 2020-06-27 15:56+0000\n"
|
||||
"Last-Translator: Safihre <safihre@sabnzbd.org>, 2020\n"
|
||||
"Language-Team: Finnish (https://www.transifex.com/sabnzbd/teams/111101/fi/)\n"
|
||||
|
||||
@@ -7,7 +7,7 @@
|
||||
#
|
||||
msgid ""
|
||||
msgstr ""
|
||||
"Project-Id-Version: SABnzbd-3.2.0-develop\n"
|
||||
"Project-Id-Version: SABnzbd-3.3.0-develop\n"
|
||||
"PO-Revision-Date: 2020-06-27 15:56+0000\n"
|
||||
"Last-Translator: Safihre <safihre@sabnzbd.org>, 2020\n"
|
||||
"Language-Team: French (https://www.transifex.com/sabnzbd/teams/111101/fr/)\n"
|
||||
|
||||
@@ -7,7 +7,7 @@
|
||||
#
|
||||
msgid ""
|
||||
msgstr ""
|
||||
"Project-Id-Version: SABnzbd-3.2.0-develop\n"
|
||||
"Project-Id-Version: SABnzbd-3.3.0-develop\n"
|
||||
"PO-Revision-Date: 2020-06-27 15:56+0000\n"
|
||||
"Last-Translator: ION, 2020\n"
|
||||
"Language-Team: Hebrew (https://www.transifex.com/sabnzbd/teams/111101/he/)\n"
|
||||
|
||||
@@ -7,7 +7,7 @@
|
||||
#
|
||||
msgid ""
|
||||
msgstr ""
|
||||
"Project-Id-Version: SABnzbd-3.2.0-develop\n"
|
||||
"Project-Id-Version: SABnzbd-3.3.0-develop\n"
|
||||
"PO-Revision-Date: 2020-06-27 15:56+0000\n"
|
||||
"Last-Translator: Safihre <safihre@sabnzbd.org>, 2020\n"
|
||||
"Language-Team: Norwegian Bokmål (https://www.transifex.com/sabnzbd/teams/111101/nb/)\n"
|
||||
|
||||
@@ -7,7 +7,7 @@
|
||||
#
|
||||
msgid ""
|
||||
msgstr ""
|
||||
"Project-Id-Version: SABnzbd-3.2.0-develop\n"
|
||||
"Project-Id-Version: SABnzbd-3.3.0-develop\n"
|
||||
"PO-Revision-Date: 2020-06-27 15:56+0000\n"
|
||||
"Last-Translator: Safihre <safihre@sabnzbd.org>, 2020\n"
|
||||
"Language-Team: Dutch (https://www.transifex.com/sabnzbd/teams/111101/nl/)\n"
|
||||
|
||||
@@ -7,7 +7,7 @@
|
||||
#
|
||||
msgid ""
|
||||
msgstr ""
|
||||
"Project-Id-Version: SABnzbd-3.2.0-develop\n"
|
||||
"Project-Id-Version: SABnzbd-3.3.0-develop\n"
|
||||
"PO-Revision-Date: 2020-06-27 15:56+0000\n"
|
||||
"Last-Translator: Safihre <safihre@sabnzbd.org>, 2020\n"
|
||||
"Language-Team: Polish (https://www.transifex.com/sabnzbd/teams/111101/pl/)\n"
|
||||
|
||||
@@ -7,7 +7,7 @@
|
||||
#
|
||||
msgid ""
|
||||
msgstr ""
|
||||
"Project-Id-Version: SABnzbd-3.2.0-develop\n"
|
||||
"Project-Id-Version: SABnzbd-3.3.0-develop\n"
|
||||
"PO-Revision-Date: 2020-06-27 15:56+0000\n"
|
||||
"Last-Translator: Safihre <safihre@sabnzbd.org>, 2020\n"
|
||||
"Language-Team: Portuguese (Brazil) (https://www.transifex.com/sabnzbd/teams/111101/pt_BR/)\n"
|
||||
|
||||
@@ -7,7 +7,7 @@
|
||||
#
|
||||
msgid ""
|
||||
msgstr ""
|
||||
"Project-Id-Version: SABnzbd-3.2.0-develop\n"
|
||||
"Project-Id-Version: SABnzbd-3.3.0-develop\n"
|
||||
"PO-Revision-Date: 2020-06-27 15:56+0000\n"
|
||||
"Last-Translator: Safihre <safihre@sabnzbd.org>, 2020\n"
|
||||
"Language-Team: Romanian (https://www.transifex.com/sabnzbd/teams/111101/ro/)\n"
|
||||
|
||||
@@ -7,7 +7,7 @@
|
||||
#
|
||||
msgid ""
|
||||
msgstr ""
|
||||
"Project-Id-Version: SABnzbd-3.2.0-develop\n"
|
||||
"Project-Id-Version: SABnzbd-3.3.0-develop\n"
|
||||
"PO-Revision-Date: 2020-06-27 15:56+0000\n"
|
||||
"Last-Translator: Safihre <safihre@sabnzbd.org>, 2020\n"
|
||||
"Language-Team: Russian (https://www.transifex.com/sabnzbd/teams/111101/ru/)\n"
|
||||
|
||||
@@ -7,7 +7,7 @@
|
||||
#
|
||||
msgid ""
|
||||
msgstr ""
|
||||
"Project-Id-Version: SABnzbd-3.2.0-develop\n"
|
||||
"Project-Id-Version: SABnzbd-3.3.0-develop\n"
|
||||
"PO-Revision-Date: 2020-06-27 15:56+0000\n"
|
||||
"Last-Translator: Safihre <safihre@sabnzbd.org>, 2020\n"
|
||||
"Language-Team: Serbian (https://www.transifex.com/sabnzbd/teams/111101/sr/)\n"
|
||||
|
||||
@@ -7,7 +7,7 @@
|
||||
#
|
||||
msgid ""
|
||||
msgstr ""
|
||||
"Project-Id-Version: SABnzbd-3.2.0-develop\n"
|
||||
"Project-Id-Version: SABnzbd-3.3.0-develop\n"
|
||||
"PO-Revision-Date: 2020-06-27 15:56+0000\n"
|
||||
"Last-Translator: Safihre <safihre@sabnzbd.org>, 2020\n"
|
||||
"Language-Team: Swedish (https://www.transifex.com/sabnzbd/teams/111101/sv/)\n"
|
||||
|
||||
@@ -7,7 +7,7 @@
|
||||
#
|
||||
msgid ""
|
||||
msgstr ""
|
||||
"Project-Id-Version: SABnzbd-3.2.0-develop\n"
|
||||
"Project-Id-Version: SABnzbd-3.3.0-develop\n"
|
||||
"PO-Revision-Date: 2020-06-27 15:56+0000\n"
|
||||
"Last-Translator: Safihre <safihre@sabnzbd.org>, 2020\n"
|
||||
"Language-Team: Chinese (China) (https://www.transifex.com/sabnzbd/teams/111101/zh_CN/)\n"
|
||||
|
||||
@@ -5,7 +5,7 @@
|
||||
#
|
||||
msgid ""
|
||||
msgstr ""
|
||||
"Project-Id-Version: SABnzbd-3.2.0-develop\n"
|
||||
"Project-Id-Version: SABnzbd-3.3.0-develop\n"
|
||||
"PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n"
|
||||
"Last-Translator: team@sabnzbd.org\n"
|
||||
"Language-Team: SABnzbd <team@sabnzbd.org>\n"
|
||||
@@ -567,6 +567,15 @@ msgstr ""
|
||||
msgid "Failed moving %s to %s"
|
||||
msgstr ""
|
||||
|
||||
#. Error message
|
||||
#: sabnzbd/filesystem.py
|
||||
msgid "Blocked attempt to create directory %s"
|
||||
msgstr ""
|
||||
|
||||
#: sabnzbd/interface.py
|
||||
msgid "Refused connection from:"
|
||||
msgstr ""
|
||||
|
||||
#: sabnzbd/interface.py
|
||||
msgid "Refused connection with hostname \"%s\" from:"
|
||||
msgstr ""
|
||||
@@ -596,6 +605,7 @@ msgstr ""
|
||||
msgid "Authentication failed, check username/password."
|
||||
msgstr ""
|
||||
|
||||
#. Warning message
|
||||
#: sabnzbd/interface.py
|
||||
msgid "Unsuccessful login attempt from %s"
|
||||
msgstr ""
|
||||
@@ -2984,20 +2994,12 @@ msgstr ""
|
||||
msgid "API Key QR Code"
|
||||
msgstr ""
|
||||
|
||||
#: sabnzbd/skintext.py
|
||||
msgid "List of local network ranges"
|
||||
msgstr ""
|
||||
|
||||
#: sabnzbd/skintext.py
|
||||
msgid "All local network addresses start with these prefixes (often \"192.168.1.\")"
|
||||
msgstr ""
|
||||
|
||||
#: sabnzbd/skintext.py
|
||||
msgid "External internet access"
|
||||
msgstr ""
|
||||
|
||||
#: sabnzbd/skintext.py
|
||||
msgid "You can set access rights for systems outside your local network. Requires List of local network ranges to be defined."
|
||||
msgid "You can set access rights for systems outside your local network."
|
||||
msgstr ""
|
||||
|
||||
#: sabnzbd/skintext.py
|
||||
@@ -3262,7 +3264,7 @@ msgid "Action when unwanted extension detected"
|
||||
msgstr ""
|
||||
|
||||
#: sabnzbd/skintext.py
|
||||
msgid "Action when an unwanted extension is detected in RAR files"
|
||||
msgid "Action when an unwanted extension is detected"
|
||||
msgstr ""
|
||||
|
||||
#: sabnzbd/skintext.py
|
||||
@@ -3270,7 +3272,15 @@ msgid "Unwanted extensions"
|
||||
msgstr ""
|
||||
|
||||
#: sabnzbd/skintext.py
|
||||
msgid "List all unwanted extensions. For example: <b>exe</b> or <b>exe, com</b>"
|
||||
msgid "Blacklist"
|
||||
msgstr ""
|
||||
|
||||
#: sabnzbd/skintext.py
|
||||
msgid "Whitelist"
|
||||
msgstr ""
|
||||
|
||||
#: sabnzbd/skintext.py
|
||||
msgid "Select a mode and list all (un)wanted extensions. For example: <b>exe</b> or <b>exe, com</b>"
|
||||
msgstr ""
|
||||
|
||||
#: sabnzbd/skintext.py
|
||||
@@ -3771,6 +3781,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"
|
||||
@@ -4539,6 +4559,10 @@ msgstr ""
|
||||
msgid "View Script Log"
|
||||
msgstr ""
|
||||
|
||||
#: sabnzbd/skintext.py
|
||||
msgid "Renaming the job will abort Direct Unpack."
|
||||
msgstr ""
|
||||
|
||||
#: sabnzbd/skintext.py
|
||||
msgid "LocalStorage (cookies) are disabled in your browser, interface settings will be lost after you close the browser!"
|
||||
msgstr ""
|
||||
|
||||
@@ -8,7 +8,7 @@
|
||||
#
|
||||
msgid ""
|
||||
msgstr ""
|
||||
"Project-Id-Version: SABnzbd-3.2.0-develop\n"
|
||||
"Project-Id-Version: SABnzbd-3.3.0-develop\n"
|
||||
"PO-Revision-Date: 2020-06-27 15:49+0000\n"
|
||||
"Last-Translator: Pavel C <quoing_transifex@mess.cz>, 2021\n"
|
||||
"Language-Team: Czech (https://www.transifex.com/sabnzbd/teams/111101/cs/)\n"
|
||||
@@ -596,6 +596,15 @@ msgstr "Chyba vytváření (%s)"
|
||||
msgid "Failed moving %s to %s"
|
||||
msgstr "Chyba přesunu %s do %s"
|
||||
|
||||
#. Error message
|
||||
#: sabnzbd/filesystem.py
|
||||
msgid "Blocked attempt to create directory %s"
|
||||
msgstr ""
|
||||
|
||||
#: sabnzbd/interface.py
|
||||
msgid "Refused connection from:"
|
||||
msgstr ""
|
||||
|
||||
#: sabnzbd/interface.py
|
||||
msgid "Refused connection with hostname \"%s\" from:"
|
||||
msgstr "Odmítnuté spojení s hostem \"%s\" z:"
|
||||
@@ -637,6 +646,7 @@ msgstr ""
|
||||
msgid "Authentication failed, check username/password."
|
||||
msgstr "Přihlášené selhalo, zkontrolujte jméno a heslo."
|
||||
|
||||
#. Warning message
|
||||
#: sabnzbd/interface.py
|
||||
msgid "Unsuccessful login attempt from %s"
|
||||
msgstr "Nezdařený pokus o přihlášení od %s"
|
||||
@@ -3096,23 +3106,12 @@ msgstr "Generovat nový klíč"
|
||||
msgid "API Key QR Code"
|
||||
msgstr ""
|
||||
|
||||
#: sabnzbd/skintext.py
|
||||
msgid "List of local network ranges"
|
||||
msgstr ""
|
||||
|
||||
#: sabnzbd/skintext.py
|
||||
msgid ""
|
||||
"All local network addresses start with these prefixes (often \"192.168.1.\")"
|
||||
msgstr ""
|
||||
|
||||
#: sabnzbd/skintext.py
|
||||
msgid "External internet access"
|
||||
msgstr ""
|
||||
|
||||
#: sabnzbd/skintext.py
|
||||
msgid ""
|
||||
"You can set access rights for systems outside your local network. Requires "
|
||||
"List of local network ranges to be defined."
|
||||
msgid "You can set access rights for systems outside your local network."
|
||||
msgstr ""
|
||||
|
||||
#: sabnzbd/skintext.py
|
||||
@@ -3408,16 +3407,25 @@ msgid "Action when unwanted extension detected"
|
||||
msgstr ""
|
||||
|
||||
#: sabnzbd/skintext.py
|
||||
msgid "Action when an unwanted extension is detected in RAR files"
|
||||
msgid "Action when an unwanted extension is detected"
|
||||
msgstr ""
|
||||
|
||||
#: sabnzbd/skintext.py
|
||||
msgid "Unwanted extensions"
|
||||
msgstr ""
|
||||
|
||||
#: sabnzbd/skintext.py
|
||||
msgid "Blacklist"
|
||||
msgstr ""
|
||||
|
||||
#: sabnzbd/skintext.py
|
||||
msgid "Whitelist"
|
||||
msgstr ""
|
||||
|
||||
#: sabnzbd/skintext.py
|
||||
msgid ""
|
||||
"List all unwanted extensions. For example: <b>exe</b> or <b>exe, com</b>"
|
||||
"Select a mode and list all (un)wanted extensions. For example: <b>exe</b> or"
|
||||
" <b>exe, com</b>"
|
||||
msgstr ""
|
||||
|
||||
#: sabnzbd/skintext.py
|
||||
@@ -3946,6 +3954,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"
|
||||
@@ -4724,6 +4742,10 @@ msgstr ""
|
||||
msgid "View Script Log"
|
||||
msgstr ""
|
||||
|
||||
#: sabnzbd/skintext.py
|
||||
msgid "Renaming the job will abort Direct Unpack."
|
||||
msgstr ""
|
||||
|
||||
#: sabnzbd/skintext.py
|
||||
msgid ""
|
||||
"LocalStorage (cookies) are disabled in your browser, interface settings will"
|
||||
|
||||
@@ -7,7 +7,7 @@
|
||||
#
|
||||
msgid ""
|
||||
msgstr ""
|
||||
"Project-Id-Version: SABnzbd-3.2.0-develop\n"
|
||||
"Project-Id-Version: SABnzbd-3.3.0-develop\n"
|
||||
"PO-Revision-Date: 2020-06-27 15:49+0000\n"
|
||||
"Last-Translator: Safihre <safihre@sabnzbd.org>, 2020\n"
|
||||
"Language-Team: Danish (https://www.transifex.com/sabnzbd/teams/111101/da/)\n"
|
||||
@@ -607,6 +607,15 @@ msgstr "Oprettelse af (%s) mislykkedes"
|
||||
msgid "Failed moving %s to %s"
|
||||
msgstr "Det lykkedes ikke at flytte %s til %s"
|
||||
|
||||
#. Error message
|
||||
#: sabnzbd/filesystem.py
|
||||
msgid "Blocked attempt to create directory %s"
|
||||
msgstr ""
|
||||
|
||||
#: sabnzbd/interface.py
|
||||
msgid "Refused connection from:"
|
||||
msgstr ""
|
||||
|
||||
#: sabnzbd/interface.py
|
||||
msgid "Refused connection with hostname \"%s\" from:"
|
||||
msgstr ""
|
||||
@@ -648,6 +657,7 @@ msgstr ""
|
||||
msgid "Authentication failed, check username/password."
|
||||
msgstr "Godkendelse mislykkedes, kontrollere brugernavn/adgangskode."
|
||||
|
||||
#. Warning message
|
||||
#: sabnzbd/interface.py
|
||||
msgid "Unsuccessful login attempt from %s"
|
||||
msgstr "Mislykkede login forsøg fra %s"
|
||||
@@ -3153,28 +3163,13 @@ msgstr "Generere Ny Nøgle"
|
||||
msgid "API Key QR Code"
|
||||
msgstr "API nøgle QR kode"
|
||||
|
||||
#: sabnzbd/skintext.py
|
||||
msgid "List of local network ranges"
|
||||
msgstr "Liste over lokale netværk intervaller"
|
||||
|
||||
#: sabnzbd/skintext.py
|
||||
msgid ""
|
||||
"All local network addresses start with these prefixes (often \"192.168.1.\")"
|
||||
msgstr ""
|
||||
"Alle lokale netværksadresser starter med disse præfikser (ofte "
|
||||
"\"192.168.1.\")"
|
||||
|
||||
#: sabnzbd/skintext.py
|
||||
msgid "External internet access"
|
||||
msgstr "Eksterne internetadgang"
|
||||
|
||||
#: sabnzbd/skintext.py
|
||||
msgid ""
|
||||
"You can set access rights for systems outside your local network. Requires "
|
||||
"List of local network ranges to be defined."
|
||||
msgid "You can set access rights for systems outside your local network."
|
||||
msgstr ""
|
||||
"Du kan angive adgangsrettigheder for systemer uden for dit lokale netværk. "
|
||||
"Kræver liste over lokale netværks intervaller, skal defineres."
|
||||
|
||||
#: sabnzbd/skintext.py
|
||||
msgid "No access"
|
||||
@@ -3495,18 +3490,26 @@ msgid "Action when unwanted extension detected"
|
||||
msgstr "Aktion når uønsket extension er fundet"
|
||||
|
||||
#: sabnzbd/skintext.py
|
||||
msgid "Action when an unwanted extension is detected in RAR files"
|
||||
msgstr "Aktion når uønsket extension er fundet i RAR fil"
|
||||
msgid "Action when an unwanted extension is detected"
|
||||
msgstr ""
|
||||
|
||||
#: sabnzbd/skintext.py
|
||||
msgid "Unwanted extensions"
|
||||
msgstr "Uønsket extension"
|
||||
|
||||
#: sabnzbd/skintext.py
|
||||
msgid ""
|
||||
"List all unwanted extensions. For example: <b>exe</b> or <b>exe, com</b>"
|
||||
msgid "Blacklist"
|
||||
msgstr ""
|
||||
|
||||
#: sabnzbd/skintext.py
|
||||
msgid "Whitelist"
|
||||
msgstr ""
|
||||
|
||||
#: sabnzbd/skintext.py
|
||||
msgid ""
|
||||
"Select a mode and list all (un)wanted extensions. For example: <b>exe</b> or"
|
||||
" <b>exe, com</b>"
|
||||
msgstr ""
|
||||
"Vis alle uønskede extensions. For eksempel: <b>exe</b> or <b>exe, com</b>"
|
||||
|
||||
#: sabnzbd/skintext.py
|
||||
msgid "Enable SFV-based checks"
|
||||
@@ -4054,6 +4057,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"
|
||||
@@ -4842,6 +4855,10 @@ msgstr "Skjul/vis komplette filer"
|
||||
msgid "View Script Log"
|
||||
msgstr "Vis scriptlog"
|
||||
|
||||
#: sabnzbd/skintext.py
|
||||
msgid "Renaming the job will abort Direct Unpack."
|
||||
msgstr ""
|
||||
|
||||
#: sabnzbd/skintext.py
|
||||
msgid ""
|
||||
"LocalStorage (cookies) are disabled in your browser, interface settings will"
|
||||
|
||||
@@ -10,7 +10,7 @@
|
||||
#
|
||||
msgid ""
|
||||
msgstr ""
|
||||
"Project-Id-Version: SABnzbd-3.2.0-develop\n"
|
||||
"Project-Id-Version: SABnzbd-3.3.0-develop\n"
|
||||
"PO-Revision-Date: 2020-06-27 15:49+0000\n"
|
||||
"Last-Translator: reloxx13 <reloxx@interia.pl>, 2021\n"
|
||||
"Language-Team: German (https://www.transifex.com/sabnzbd/teams/111101/de/)\n"
|
||||
@@ -628,6 +628,15 @@ msgstr "Erstellen von %s fehlgeschlagen"
|
||||
msgid "Failed moving %s to %s"
|
||||
msgstr "Verschieben von %s nach %s fehlgeschlagen"
|
||||
|
||||
#. Error message
|
||||
#: sabnzbd/filesystem.py
|
||||
msgid "Blocked attempt to create directory %s"
|
||||
msgstr ""
|
||||
|
||||
#: sabnzbd/interface.py
|
||||
msgid "Refused connection from:"
|
||||
msgstr ""
|
||||
|
||||
#: sabnzbd/interface.py
|
||||
msgid "Refused connection with hostname \"%s\" from:"
|
||||
msgstr "Verbindung vom Host \"%s\" abgelehnt von:"
|
||||
@@ -670,6 +679,7 @@ msgid "Authentication failed, check username/password."
|
||||
msgstr ""
|
||||
"Authentifizierung fehlgeschlagen. Überprüfen Sie Benutzername und Passwort."
|
||||
|
||||
#. Warning message
|
||||
#: sabnzbd/interface.py
|
||||
msgid "Unsuccessful login attempt from %s"
|
||||
msgstr "Fehlerhafter Login Versuch von %s"
|
||||
@@ -3232,28 +3242,13 @@ msgstr "Neuen Schlüssel generieren"
|
||||
msgid "API Key QR Code"
|
||||
msgstr "API-Key OR-Code"
|
||||
|
||||
#: sabnzbd/skintext.py
|
||||
msgid "List of local network ranges"
|
||||
msgstr "Liste der lokalen Netzwerkadressenbereiche"
|
||||
|
||||
#: sabnzbd/skintext.py
|
||||
msgid ""
|
||||
"All local network addresses start with these prefixes (often \"192.168.1.\")"
|
||||
msgstr ""
|
||||
"Alle lokalen Netzwerkadressen starten mit diesen Präfixen (oft "
|
||||
"\"192.168.1.1\")"
|
||||
|
||||
#: sabnzbd/skintext.py
|
||||
msgid "External internet access"
|
||||
msgstr "Externer Internetzugriff"
|
||||
|
||||
#: sabnzbd/skintext.py
|
||||
msgid ""
|
||||
"You can set access rights for systems outside your local network. Requires "
|
||||
"List of local network ranges to be defined."
|
||||
msgid "You can set access rights for systems outside your local network."
|
||||
msgstr ""
|
||||
"Du kannst Zugriffsrechte für Systeme ausserhalb deines Netzwerkes setzen. "
|
||||
"Benötigt die Definition einer Liste von lokalen Netzwerkbereichen."
|
||||
|
||||
#: sabnzbd/skintext.py
|
||||
msgid "No access"
|
||||
@@ -3592,19 +3587,26 @@ msgid "Action when unwanted extension detected"
|
||||
msgstr "Aktion bei ungewollter Dateienendung"
|
||||
|
||||
#: sabnzbd/skintext.py
|
||||
msgid "Action when an unwanted extension is detected in RAR files"
|
||||
msgstr "Aktion bei ungewollter Dateiendung innerhalb RAR-Archiven"
|
||||
msgid "Action when an unwanted extension is detected"
|
||||
msgstr ""
|
||||
|
||||
#: sabnzbd/skintext.py
|
||||
msgid "Unwanted extensions"
|
||||
msgstr "Ungewollte Dateiendungen"
|
||||
|
||||
#: sabnzbd/skintext.py
|
||||
msgid ""
|
||||
"List all unwanted extensions. For example: <b>exe</b> or <b>exe, com</b>"
|
||||
msgid "Blacklist"
|
||||
msgstr ""
|
||||
|
||||
#: sabnzbd/skintext.py
|
||||
msgid "Whitelist"
|
||||
msgstr ""
|
||||
|
||||
#: sabnzbd/skintext.py
|
||||
msgid ""
|
||||
"Select a mode and list all (un)wanted extensions. For example: <b>exe</b> or"
|
||||
" <b>exe, com</b>"
|
||||
msgstr ""
|
||||
"Liste aller ungewollter Dateiendungen. Zum Beispiel: <b>exe</b> or <b>exe, "
|
||||
"com</b>"
|
||||
|
||||
#: sabnzbd/skintext.py
|
||||
msgid "Enable SFV-based checks"
|
||||
@@ -4174,6 +4176,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"
|
||||
@@ -4966,6 +4978,10 @@ msgstr "Vollendete Dateien anzeigen/verstecken"
|
||||
msgid "View Script Log"
|
||||
msgstr "Skript-Protokoll anzeigen"
|
||||
|
||||
#: sabnzbd/skintext.py
|
||||
msgid "Renaming the job will abort Direct Unpack."
|
||||
msgstr ""
|
||||
|
||||
#: sabnzbd/skintext.py
|
||||
msgid ""
|
||||
"LocalStorage (cookies) are disabled in your browser, interface settings will"
|
||||
|
||||
@@ -9,7 +9,7 @@
|
||||
#
|
||||
msgid ""
|
||||
msgstr ""
|
||||
"Project-Id-Version: SABnzbd-3.2.0-develop\n"
|
||||
"Project-Id-Version: SABnzbd-3.3.0-develop\n"
|
||||
"PO-Revision-Date: 2020-06-27 15:49+0000\n"
|
||||
"Last-Translator: 1024mb <angelb2203@gmail.com>, 2020\n"
|
||||
"Language-Team: Spanish (https://www.transifex.com/sabnzbd/teams/111101/es/)\n"
|
||||
@@ -628,6 +628,15 @@ msgstr "Error al crear (%s)"
|
||||
msgid "Failed moving %s to %s"
|
||||
msgstr "Error al mover %s a %s"
|
||||
|
||||
#. Error message
|
||||
#: sabnzbd/filesystem.py
|
||||
msgid "Blocked attempt to create directory %s"
|
||||
msgstr ""
|
||||
|
||||
#: sabnzbd/interface.py
|
||||
msgid "Refused connection from:"
|
||||
msgstr ""
|
||||
|
||||
#: sabnzbd/interface.py
|
||||
msgid "Refused connection with hostname \"%s\" from:"
|
||||
msgstr "Se deniega la conexión con el nombre de equipo \"%s\" desde:"
|
||||
@@ -669,6 +678,7 @@ msgstr ""
|
||||
msgid "Authentication failed, check username/password."
|
||||
msgstr "Autenticación fallida, compruebe el usuario o la contraseña."
|
||||
|
||||
#. Warning message
|
||||
#: sabnzbd/interface.py
|
||||
msgid "Unsuccessful login attempt from %s"
|
||||
msgstr "Intento fallido de inicio de sesión desde %s"
|
||||
@@ -3235,28 +3245,13 @@ msgstr "Generar nueva clave"
|
||||
msgid "API Key QR Code"
|
||||
msgstr "Código QR de la clave API"
|
||||
|
||||
#: sabnzbd/skintext.py
|
||||
msgid "List of local network ranges"
|
||||
msgstr "Lista de rangos de red local"
|
||||
|
||||
#: sabnzbd/skintext.py
|
||||
msgid ""
|
||||
"All local network addresses start with these prefixes (often \"192.168.1.\")"
|
||||
msgstr ""
|
||||
"Todas las direcciones de red locales comienzan con estos prefijos (a menudo "
|
||||
"\" 192.168.1 . \" )"
|
||||
|
||||
#: sabnzbd/skintext.py
|
||||
msgid "External internet access"
|
||||
msgstr "Acceso a internet externa"
|
||||
|
||||
#: sabnzbd/skintext.py
|
||||
msgid ""
|
||||
"You can set access rights for systems outside your local network. Requires "
|
||||
"List of local network ranges to be defined."
|
||||
msgid "You can set access rights for systems outside your local network."
|
||||
msgstr ""
|
||||
"Puede configurar los derechos de acceso para los sistemas fuera de su red "
|
||||
"local. Es necesario definir los rangos de la lista de red local."
|
||||
|
||||
#: sabnzbd/skintext.py
|
||||
msgid "No access"
|
||||
@@ -3583,19 +3578,26 @@ msgid "Action when unwanted extension detected"
|
||||
msgstr "Acción al detectar extensiones no deseadas"
|
||||
|
||||
#: sabnzbd/skintext.py
|
||||
msgid "Action when an unwanted extension is detected in RAR files"
|
||||
msgstr "Acción cuando se detecta una extensión no deseada en archivos RAR"
|
||||
msgid "Action when an unwanted extension is detected"
|
||||
msgstr ""
|
||||
|
||||
#: sabnzbd/skintext.py
|
||||
msgid "Unwanted extensions"
|
||||
msgstr "extensiones no deseadas"
|
||||
|
||||
#: sabnzbd/skintext.py
|
||||
msgid ""
|
||||
"List all unwanted extensions. For example: <b>exe</b> or <b>exe, com</b>"
|
||||
msgid "Blacklist"
|
||||
msgstr ""
|
||||
|
||||
#: sabnzbd/skintext.py
|
||||
msgid "Whitelist"
|
||||
msgstr ""
|
||||
|
||||
#: sabnzbd/skintext.py
|
||||
msgid ""
|
||||
"Select a mode and list all (un)wanted extensions. For example: <b>exe</b> or"
|
||||
" <b>exe, com</b>"
|
||||
msgstr ""
|
||||
"Enumerar todas las extensiones no deseadas . Por ejemplo : < b> exe < / b > "
|
||||
"o < b> exe, com < / b >"
|
||||
|
||||
#: sabnzbd/skintext.py
|
||||
msgid "Enable SFV-based checks"
|
||||
@@ -4166,6 +4168,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"
|
||||
@@ -4960,6 +4972,10 @@ msgstr "Ocultar/Mostrar ficheros completados"
|
||||
msgid "View Script Log"
|
||||
msgstr "Ver bitacora de Scripts"
|
||||
|
||||
#: sabnzbd/skintext.py
|
||||
msgid "Renaming the job will abort Direct Unpack."
|
||||
msgstr ""
|
||||
|
||||
#: sabnzbd/skintext.py
|
||||
msgid ""
|
||||
"LocalStorage (cookies) are disabled in your browser, interface settings will"
|
||||
|
||||
@@ -7,7 +7,7 @@
|
||||
#
|
||||
msgid ""
|
||||
msgstr ""
|
||||
"Project-Id-Version: SABnzbd-3.2.0-develop\n"
|
||||
"Project-Id-Version: SABnzbd-3.3.0-develop\n"
|
||||
"PO-Revision-Date: 2020-06-27 15:49+0000\n"
|
||||
"Last-Translator: Safihre <safihre@sabnzbd.org>, 2020\n"
|
||||
"Language-Team: Finnish (https://www.transifex.com/sabnzbd/teams/111101/fi/)\n"
|
||||
@@ -603,6 +603,15 @@ msgstr "Kohteen (%s) luominen epäonnistui"
|
||||
msgid "Failed moving %s to %s"
|
||||
msgstr "Kohteen %s siirtäminen kohteeseen %s epäonnistui"
|
||||
|
||||
#. Error message
|
||||
#: sabnzbd/filesystem.py
|
||||
msgid "Blocked attempt to create directory %s"
|
||||
msgstr ""
|
||||
|
||||
#: sabnzbd/interface.py
|
||||
msgid "Refused connection from:"
|
||||
msgstr ""
|
||||
|
||||
#: sabnzbd/interface.py
|
||||
msgid "Refused connection with hostname \"%s\" from:"
|
||||
msgstr ""
|
||||
@@ -644,6 +653,7 @@ msgstr ""
|
||||
msgid "Authentication failed, check username/password."
|
||||
msgstr "Varmennus epäonnistui, tarkista käyttäjänimi/salasana."
|
||||
|
||||
#. Warning message
|
||||
#: sabnzbd/interface.py
|
||||
msgid "Unsuccessful login attempt from %s"
|
||||
msgstr ""
|
||||
@@ -3152,25 +3162,12 @@ msgstr "Luo uusi avain"
|
||||
msgid "API Key QR Code"
|
||||
msgstr "API avaimen QR-koodi"
|
||||
|
||||
#: sabnzbd/skintext.py
|
||||
msgid "List of local network ranges"
|
||||
msgstr "Lista paikallisista verkko-osoitealueista"
|
||||
|
||||
#: sabnzbd/skintext.py
|
||||
msgid ""
|
||||
"All local network addresses start with these prefixes (often \"192.168.1.\")"
|
||||
msgstr ""
|
||||
"Kaikki paikalliset verkko-osoitteet alkavat näillä etuliitteillä (yleensä "
|
||||
"\"192.168.1.\")"
|
||||
|
||||
#: sabnzbd/skintext.py
|
||||
msgid "External internet access"
|
||||
msgstr "Ulkoinen ohjelman käyttö"
|
||||
|
||||
#: sabnzbd/skintext.py
|
||||
msgid ""
|
||||
"You can set access rights for systems outside your local network. Requires "
|
||||
"List of local network ranges to be defined."
|
||||
msgid "You can set access rights for systems outside your local network."
|
||||
msgstr ""
|
||||
|
||||
#: sabnzbd/skintext.py
|
||||
@@ -3492,19 +3489,26 @@ msgid "Action when unwanted extension detected"
|
||||
msgstr "Toiminto kun havaitaan ei toivottu tiedostopääte"
|
||||
|
||||
#: sabnzbd/skintext.py
|
||||
msgid "Action when an unwanted extension is detected in RAR files"
|
||||
msgstr "Toiminto kun ei toivottu tiedostopääte havaitaan RAR arkistossa"
|
||||
msgid "Action when an unwanted extension is detected"
|
||||
msgstr ""
|
||||
|
||||
#: sabnzbd/skintext.py
|
||||
msgid "Unwanted extensions"
|
||||
msgstr "Ei toivotut tiedostopäätteet"
|
||||
|
||||
#: sabnzbd/skintext.py
|
||||
msgid ""
|
||||
"List all unwanted extensions. For example: <b>exe</b> or <b>exe, com</b>"
|
||||
msgid "Blacklist"
|
||||
msgstr ""
|
||||
|
||||
#: sabnzbd/skintext.py
|
||||
msgid "Whitelist"
|
||||
msgstr ""
|
||||
|
||||
#: sabnzbd/skintext.py
|
||||
msgid ""
|
||||
"Select a mode and list all (un)wanted extensions. For example: <b>exe</b> or"
|
||||
" <b>exe, com</b>"
|
||||
msgstr ""
|
||||
"Lista ei toivotuista tiedostopäätteistä. Esimerkiksi: <b>exe</b> tai <b>exe,"
|
||||
" com</b>"
|
||||
|
||||
#: sabnzbd/skintext.py
|
||||
msgid "Enable SFV-based checks"
|
||||
@@ -4053,6 +4057,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"
|
||||
@@ -4843,6 +4857,10 @@ msgstr "Piilota/näytä valmistuneet tiedostot"
|
||||
msgid "View Script Log"
|
||||
msgstr "Näytä skriptien loki"
|
||||
|
||||
#: sabnzbd/skintext.py
|
||||
msgid "Renaming the job will abort Direct Unpack."
|
||||
msgstr ""
|
||||
|
||||
#: sabnzbd/skintext.py
|
||||
msgid ""
|
||||
"LocalStorage (cookies) are disabled in your browser, interface settings will"
|
||||
|
||||
@@ -8,7 +8,7 @@
|
||||
#
|
||||
msgid ""
|
||||
msgstr ""
|
||||
"Project-Id-Version: SABnzbd-3.2.0-develop\n"
|
||||
"Project-Id-Version: SABnzbd-3.3.0-develop\n"
|
||||
"PO-Revision-Date: 2020-06-27 15:49+0000\n"
|
||||
"Last-Translator: Fred L <88com88@gmail.com>, 2021\n"
|
||||
"Language-Team: French (https://www.transifex.com/sabnzbd/teams/111101/fr/)\n"
|
||||
@@ -630,6 +630,15 @@ msgstr "Échec lors de la création de (%s)"
|
||||
msgid "Failed moving %s to %s"
|
||||
msgstr "Échec lors du déplacement de %s vers %s"
|
||||
|
||||
#. Error message
|
||||
#: sabnzbd/filesystem.py
|
||||
msgid "Blocked attempt to create directory %s"
|
||||
msgstr "Tentative bloquée de création du répertoire %s"
|
||||
|
||||
#: sabnzbd/interface.py
|
||||
msgid "Refused connection from:"
|
||||
msgstr ""
|
||||
|
||||
#: sabnzbd/interface.py
|
||||
msgid "Refused connection with hostname \"%s\" from:"
|
||||
msgstr "Connexion refusée avec le nom d'hôte \"%s\" à partir de :"
|
||||
@@ -671,6 +680,7 @@ msgstr ""
|
||||
msgid "Authentication failed, check username/password."
|
||||
msgstr "Echec d'authentification, vérifiez les identifiant/mot de passe."
|
||||
|
||||
#. Warning message
|
||||
#: sabnzbd/interface.py
|
||||
msgid "Unsuccessful login attempt from %s"
|
||||
msgstr "Echec de la tentative de connexion de %s"
|
||||
@@ -3234,28 +3244,13 @@ msgstr "Générer une nouvelle clé"
|
||||
msgid "API Key QR Code"
|
||||
msgstr "Clé API code QR"
|
||||
|
||||
#: sabnzbd/skintext.py
|
||||
msgid "List of local network ranges"
|
||||
msgstr "Liste des plages de réseau local"
|
||||
|
||||
#: sabnzbd/skintext.py
|
||||
msgid ""
|
||||
"All local network addresses start with these prefixes (often \"192.168.1.\")"
|
||||
msgstr ""
|
||||
"Toutes les adresses de réseau local commencent par ces préfixes (souvent "
|
||||
"\"192.168.1.\" )"
|
||||
|
||||
#: sabnzbd/skintext.py
|
||||
msgid "External internet access"
|
||||
msgstr "Accès Internet externe"
|
||||
|
||||
#: sabnzbd/skintext.py
|
||||
msgid ""
|
||||
"You can set access rights for systems outside your local network. Requires "
|
||||
"List of local network ranges to be defined."
|
||||
msgid "You can set access rights for systems outside your local network."
|
||||
msgstr ""
|
||||
"Vous pouvez définir les droits d'accès pour les systèmes en dehors de votre "
|
||||
"réseau local. Requiert la liste des plages de réseaux locaux à définir."
|
||||
|
||||
#: sabnzbd/skintext.py
|
||||
msgid "No access"
|
||||
@@ -3594,19 +3589,28 @@ msgid "Action when unwanted extension detected"
|
||||
msgstr "Action si une extension indésirable est détecté"
|
||||
|
||||
#: sabnzbd/skintext.py
|
||||
msgid "Action when an unwanted extension is detected in RAR files"
|
||||
msgstr "Action si une extension indésirable est détecté dans les fichiers RAR"
|
||||
msgid "Action when an unwanted extension is detected"
|
||||
msgstr "Action lorsqu'une extension indésirable est détectée"
|
||||
|
||||
#: sabnzbd/skintext.py
|
||||
msgid "Unwanted extensions"
|
||||
msgstr "Extensions indésirables"
|
||||
|
||||
#: sabnzbd/skintext.py
|
||||
msgid "Blacklist"
|
||||
msgstr "Liste noire"
|
||||
|
||||
#: sabnzbd/skintext.py
|
||||
msgid "Whitelist"
|
||||
msgstr "Liste blanche"
|
||||
|
||||
#: sabnzbd/skintext.py
|
||||
msgid ""
|
||||
"List all unwanted extensions. For example: <b>exe</b> or <b>exe, com</b>"
|
||||
"Select a mode and list all (un)wanted extensions. For example: <b>exe</b> or"
|
||||
" <b>exe, com</b>"
|
||||
msgstr ""
|
||||
"Afficher toutes les extensions indésirables. Par exemple : <b>exe</b> or "
|
||||
"<b>exe, com</b>"
|
||||
"Sélectionnez un mode et listez toutes les extensions (non) souhaitées. Par "
|
||||
"exemple: <b>exe</b> ou <b>exe, com</b>"
|
||||
|
||||
#: sabnzbd/skintext.py
|
||||
msgid "Enable SFV-based checks"
|
||||
@@ -4182,6 +4186,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 "Modifier"
|
||||
|
||||
#. Config->RSS when will be the next RSS scan
|
||||
#: sabnzbd/skintext.py
|
||||
msgid "Next scan at"
|
||||
msgstr "Prochain scan à"
|
||||
|
||||
#. Config->RSS table column header
|
||||
#: sabnzbd/skintext.py
|
||||
msgid "Filter"
|
||||
@@ -4978,6 +4992,10 @@ msgstr "Afficher/masquer les fichiers terminés"
|
||||
msgid "View Script Log"
|
||||
msgstr "Afficher le journal des scripts"
|
||||
|
||||
#: sabnzbd/skintext.py
|
||||
msgid "Renaming the job will abort Direct Unpack."
|
||||
msgstr "Renommer la tâche annulera la Décompression Directe."
|
||||
|
||||
#: sabnzbd/skintext.py
|
||||
msgid ""
|
||||
"LocalStorage (cookies) are disabled in your browser, interface settings will"
|
||||
|
||||
1072
po/main/he.po
1072
po/main/he.po
File diff suppressed because it is too large
Load Diff
@@ -7,7 +7,7 @@
|
||||
#
|
||||
msgid ""
|
||||
msgstr ""
|
||||
"Project-Id-Version: SABnzbd-3.2.0-develop\n"
|
||||
"Project-Id-Version: SABnzbd-3.3.0-develop\n"
|
||||
"PO-Revision-Date: 2020-06-27 15:49+0000\n"
|
||||
"Last-Translator: Safihre <safihre@sabnzbd.org>, 2020\n"
|
||||
"Language-Team: Norwegian Bokmål (https://www.transifex.com/sabnzbd/teams/111101/nb/)\n"
|
||||
@@ -599,6 +599,15 @@ msgstr "Opprettelse av (%s) mislyktes"
|
||||
msgid "Failed moving %s to %s"
|
||||
msgstr "Kunne ikke flytte %s til %s"
|
||||
|
||||
#. Error message
|
||||
#: sabnzbd/filesystem.py
|
||||
msgid "Blocked attempt to create directory %s"
|
||||
msgstr ""
|
||||
|
||||
#: sabnzbd/interface.py
|
||||
msgid "Refused connection from:"
|
||||
msgstr ""
|
||||
|
||||
#: sabnzbd/interface.py
|
||||
msgid "Refused connection with hostname \"%s\" from:"
|
||||
msgstr ""
|
||||
@@ -640,6 +649,7 @@ msgstr ""
|
||||
msgid "Authentication failed, check username/password."
|
||||
msgstr "Godkjenning mislyktes, kontroller brukernavn og passord."
|
||||
|
||||
#. Warning message
|
||||
#: sabnzbd/interface.py
|
||||
msgid "Unsuccessful login attempt from %s"
|
||||
msgstr "Mislykket påloggingsforsøk fra %s"
|
||||
@@ -3140,24 +3150,12 @@ msgstr "Generer Ny Nøkkel"
|
||||
msgid "API Key QR Code"
|
||||
msgstr "API-nøkkel QR-kode"
|
||||
|
||||
#: sabnzbd/skintext.py
|
||||
msgid "List of local network ranges"
|
||||
msgstr "Liste over lokale nettverksområder"
|
||||
|
||||
#: sabnzbd/skintext.py
|
||||
msgid ""
|
||||
"All local network addresses start with these prefixes (often \"192.168.1.\")"
|
||||
msgstr ""
|
||||
"Alle lokale nettverksadresser starter med disse prefix (ofte \"192.168.1.\")"
|
||||
|
||||
#: sabnzbd/skintext.py
|
||||
msgid "External internet access"
|
||||
msgstr "Ekstern internettilgang"
|
||||
|
||||
#: sabnzbd/skintext.py
|
||||
msgid ""
|
||||
"You can set access rights for systems outside your local network. Requires "
|
||||
"List of local network ranges to be defined."
|
||||
msgid "You can set access rights for systems outside your local network."
|
||||
msgstr ""
|
||||
|
||||
#: sabnzbd/skintext.py
|
||||
@@ -3474,19 +3472,26 @@ msgid "Action when unwanted extension detected"
|
||||
msgstr "Handling når uønsket filtype oppdaget"
|
||||
|
||||
#: sabnzbd/skintext.py
|
||||
msgid "Action when an unwanted extension is detected in RAR files"
|
||||
msgstr "Handling når uønsket filtype blir oppdaget i RAR filer."
|
||||
msgid "Action when an unwanted extension is detected"
|
||||
msgstr ""
|
||||
|
||||
#: sabnzbd/skintext.py
|
||||
msgid "Unwanted extensions"
|
||||
msgstr "Uønsket filtyper"
|
||||
|
||||
#: sabnzbd/skintext.py
|
||||
msgid ""
|
||||
"List all unwanted extensions. For example: <b>exe</b> or <b>exe, com</b>"
|
||||
msgid "Blacklist"
|
||||
msgstr ""
|
||||
|
||||
#: sabnzbd/skintext.py
|
||||
msgid "Whitelist"
|
||||
msgstr ""
|
||||
|
||||
#: sabnzbd/skintext.py
|
||||
msgid ""
|
||||
"Select a mode and list all (un)wanted extensions. For example: <b>exe</b> or"
|
||||
" <b>exe, com</b>"
|
||||
msgstr ""
|
||||
"Skriv alle uønskende filtyper. For eksempel: <b>exe</b> eller <b>exe, "
|
||||
"com</b>"
|
||||
|
||||
#: sabnzbd/skintext.py
|
||||
msgid "Enable SFV-based checks"
|
||||
@@ -4029,6 +4034,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"
|
||||
@@ -4814,6 +4829,10 @@ msgstr "Skjul/vis fullførte filer"
|
||||
msgid "View Script Log"
|
||||
msgstr "Se skriptlogg"
|
||||
|
||||
#: sabnzbd/skintext.py
|
||||
msgid "Renaming the job will abort Direct Unpack."
|
||||
msgstr ""
|
||||
|
||||
#: sabnzbd/skintext.py
|
||||
msgid ""
|
||||
"LocalStorage (cookies) are disabled in your browser, interface settings will"
|
||||
|
||||
@@ -7,7 +7,7 @@
|
||||
#
|
||||
msgid ""
|
||||
msgstr ""
|
||||
"Project-Id-Version: SABnzbd-3.2.0-develop\n"
|
||||
"Project-Id-Version: SABnzbd-3.3.0-develop\n"
|
||||
"PO-Revision-Date: 2020-06-27 15:49+0000\n"
|
||||
"Last-Translator: Safihre <safihre@sabnzbd.org>, 2021\n"
|
||||
"Language-Team: Dutch (https://www.transifex.com/sabnzbd/teams/111101/nl/)\n"
|
||||
@@ -619,6 +619,15 @@ msgstr "Aanmaken (%s) mislukt"
|
||||
msgid "Failed moving %s to %s"
|
||||
msgstr "Verplaatsen van %s naar %s mislukt"
|
||||
|
||||
#. Error message
|
||||
#: sabnzbd/filesystem.py
|
||||
msgid "Blocked attempt to create directory %s"
|
||||
msgstr ""
|
||||
|
||||
#: sabnzbd/interface.py
|
||||
msgid "Refused connection from:"
|
||||
msgstr ""
|
||||
|
||||
#: sabnzbd/interface.py
|
||||
msgid "Refused connection with hostname \"%s\" from:"
|
||||
msgstr "Verbinding met hostnaam \"%s\" geweigerd van:"
|
||||
@@ -660,6 +669,7 @@ msgstr ""
|
||||
msgid "Authentication failed, check username/password."
|
||||
msgstr "Inloggen mislukt, controleer gebruikersnaam en wachtwoord."
|
||||
|
||||
#. Warning message
|
||||
#: sabnzbd/interface.py
|
||||
msgid "Unsuccessful login attempt from %s"
|
||||
msgstr "Mislukte login progin bij %s"
|
||||
@@ -3204,28 +3214,13 @@ msgstr "Maak een nieuwe sleutel"
|
||||
msgid "API Key QR Code"
|
||||
msgstr "QR-code van de API-sleutel"
|
||||
|
||||
#: sabnzbd/skintext.py
|
||||
msgid "List of local network ranges"
|
||||
msgstr "Lijst van lokale netwerk bereiken"
|
||||
|
||||
#: sabnzbd/skintext.py
|
||||
msgid ""
|
||||
"All local network addresses start with these prefixes (often \"192.168.1.\")"
|
||||
msgstr ""
|
||||
"Alle lokale netwerk adressen die beginnen met deze reeks (vaak "
|
||||
"\"192.168.1.\")"
|
||||
|
||||
#: sabnzbd/skintext.py
|
||||
msgid "External internet access"
|
||||
msgstr "Externe toegang"
|
||||
|
||||
#: sabnzbd/skintext.py
|
||||
msgid ""
|
||||
"You can set access rights for systems outside your local network. Requires "
|
||||
"List of local network ranges to be defined."
|
||||
msgid "You can set access rights for systems outside your local network."
|
||||
msgstr ""
|
||||
"Je kunt toegangsrechten instellen voor systemen buiten je lokale netwerk. "
|
||||
"Hiervoor geef je een lijst van netwerk-bereiken in."
|
||||
|
||||
#: sabnzbd/skintext.py
|
||||
msgid "No access"
|
||||
@@ -3551,20 +3546,26 @@ msgid "Action when unwanted extension detected"
|
||||
msgstr "Actie bij ontdekken van ongewenste extensie"
|
||||
|
||||
#: sabnzbd/skintext.py
|
||||
msgid "Action when an unwanted extension is detected in RAR files"
|
||||
msgid "Action when an unwanted extension is detected"
|
||||
msgstr ""
|
||||
"Actie wanneer een ongewenste extensie wordt gevonden in een RAR-bestand"
|
||||
|
||||
#: sabnzbd/skintext.py
|
||||
msgid "Unwanted extensions"
|
||||
msgstr "Ongewenste extensies"
|
||||
|
||||
#: sabnzbd/skintext.py
|
||||
msgid ""
|
||||
"List all unwanted extensions. For example: <b>exe</b> or <b>exe, com</b>"
|
||||
msgid "Blacklist"
|
||||
msgstr ""
|
||||
|
||||
#: sabnzbd/skintext.py
|
||||
msgid "Whitelist"
|
||||
msgstr ""
|
||||
|
||||
#: sabnzbd/skintext.py
|
||||
msgid ""
|
||||
"Select a mode and list all (un)wanted extensions. For example: <b>exe</b> or"
|
||||
" <b>exe, com</b>"
|
||||
msgstr ""
|
||||
"Lijst van alle ongewenste extensies. Voorbeeld: <b>exe</b> or <b>exe, "
|
||||
"com</b>"
|
||||
|
||||
#: sabnzbd/skintext.py
|
||||
msgid "Enable SFV-based checks"
|
||||
@@ -4135,6 +4136,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"
|
||||
@@ -4927,6 +4938,10 @@ msgstr "Toon/verberg voltooide bestanden"
|
||||
msgid "View Script Log"
|
||||
msgstr "Toon Script resultaat"
|
||||
|
||||
#: sabnzbd/skintext.py
|
||||
msgid "Renaming the job will abort Direct Unpack."
|
||||
msgstr ""
|
||||
|
||||
#: sabnzbd/skintext.py
|
||||
msgid ""
|
||||
"LocalStorage (cookies) are disabled in your browser, interface settings will"
|
||||
|
||||
@@ -7,7 +7,7 @@
|
||||
#
|
||||
msgid ""
|
||||
msgstr ""
|
||||
"Project-Id-Version: SABnzbd-3.2.0-develop\n"
|
||||
"Project-Id-Version: SABnzbd-3.3.0-develop\n"
|
||||
"PO-Revision-Date: 2020-06-27 15:49+0000\n"
|
||||
"Last-Translator: Safihre <safihre@sabnzbd.org>, 2020\n"
|
||||
"Language-Team: Polish (https://www.transifex.com/sabnzbd/teams/111101/pl/)\n"
|
||||
@@ -598,6 +598,15 @@ msgstr "Nie udało się utworzyć (%s)"
|
||||
msgid "Failed moving %s to %s"
|
||||
msgstr "Nie udało się przenieść %s do %s"
|
||||
|
||||
#. Error message
|
||||
#: sabnzbd/filesystem.py
|
||||
msgid "Blocked attempt to create directory %s"
|
||||
msgstr ""
|
||||
|
||||
#: sabnzbd/interface.py
|
||||
msgid "Refused connection from:"
|
||||
msgstr ""
|
||||
|
||||
#: sabnzbd/interface.py
|
||||
msgid "Refused connection with hostname \"%s\" from:"
|
||||
msgstr ""
|
||||
@@ -639,6 +648,7 @@ msgstr ""
|
||||
msgid "Authentication failed, check username/password."
|
||||
msgstr "Błąd połączenia, sprawdź nazwę użytkownika i hasło."
|
||||
|
||||
#. Warning message
|
||||
#: sabnzbd/interface.py
|
||||
msgid "Unsuccessful login attempt from %s"
|
||||
msgstr ""
|
||||
@@ -3143,25 +3153,12 @@ msgstr "Utwórz nowy klucz"
|
||||
msgid "API Key QR Code"
|
||||
msgstr "Kod QR klucza API"
|
||||
|
||||
#: sabnzbd/skintext.py
|
||||
msgid "List of local network ranges"
|
||||
msgstr "Lista zakresów sieci lokalnych"
|
||||
|
||||
#: sabnzbd/skintext.py
|
||||
msgid ""
|
||||
"All local network addresses start with these prefixes (often \"192.168.1.\")"
|
||||
msgstr ""
|
||||
"Wszystkie lokalne adresy sieciowe zaczynają się od tych prefiksów (często "
|
||||
"\"192.168.1.\")"
|
||||
|
||||
#: sabnzbd/skintext.py
|
||||
msgid "External internet access"
|
||||
msgstr "Dostęp z zewnątrz"
|
||||
|
||||
#: sabnzbd/skintext.py
|
||||
msgid ""
|
||||
"You can set access rights for systems outside your local network. Requires "
|
||||
"List of local network ranges to be defined."
|
||||
msgid "You can set access rights for systems outside your local network."
|
||||
msgstr ""
|
||||
|
||||
#: sabnzbd/skintext.py
|
||||
@@ -3480,20 +3477,26 @@ msgid "Action when unwanted extension detected"
|
||||
msgstr "Działanie dla niepożądanych rozszerzeń"
|
||||
|
||||
#: sabnzbd/skintext.py
|
||||
msgid "Action when an unwanted extension is detected in RAR files"
|
||||
msgid "Action when an unwanted extension is detected"
|
||||
msgstr ""
|
||||
"Działanie, które zostanie podjęte po wykryciu w pliku RAR niepożądanego "
|
||||
"rozszerzenia"
|
||||
|
||||
#: sabnzbd/skintext.py
|
||||
msgid "Unwanted extensions"
|
||||
msgstr "Niepożądane rozszerzenia"
|
||||
|
||||
#: sabnzbd/skintext.py
|
||||
msgid ""
|
||||
"List all unwanted extensions. For example: <b>exe</b> or <b>exe, com</b>"
|
||||
msgid "Blacklist"
|
||||
msgstr ""
|
||||
|
||||
#: sabnzbd/skintext.py
|
||||
msgid "Whitelist"
|
||||
msgstr ""
|
||||
|
||||
#: sabnzbd/skintext.py
|
||||
msgid ""
|
||||
"Select a mode and list all (un)wanted extensions. For example: <b>exe</b> or"
|
||||
" <b>exe, com</b>"
|
||||
msgstr ""
|
||||
"Lista niepożądanych rozszerzeń. Przykład: <b>exe</b> lub <b>exe, com</b>"
|
||||
|
||||
#: sabnzbd/skintext.py
|
||||
msgid "Enable SFV-based checks"
|
||||
@@ -4039,6 +4042,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"
|
||||
@@ -4824,6 +4837,10 @@ msgstr "Pokaż/ukryj ukończone pliki"
|
||||
msgid "View Script Log"
|
||||
msgstr "Zobacz log skryptu"
|
||||
|
||||
#: sabnzbd/skintext.py
|
||||
msgid "Renaming the job will abort Direct Unpack."
|
||||
msgstr ""
|
||||
|
||||
#: sabnzbd/skintext.py
|
||||
msgid ""
|
||||
"LocalStorage (cookies) are disabled in your browser, interface settings will"
|
||||
|
||||
@@ -7,7 +7,7 @@
|
||||
#
|
||||
msgid ""
|
||||
msgstr ""
|
||||
"Project-Id-Version: SABnzbd-3.2.0-develop\n"
|
||||
"Project-Id-Version: SABnzbd-3.3.0-develop\n"
|
||||
"PO-Revision-Date: 2020-06-27 15:49+0000\n"
|
||||
"Last-Translator: Safihre <safihre@sabnzbd.org>, 2020\n"
|
||||
"Language-Team: Portuguese (Brazil) (https://www.transifex.com/sabnzbd/teams/111101/pt_BR/)\n"
|
||||
@@ -602,6 +602,15 @@ msgstr "Falha ao criar (%s)"
|
||||
msgid "Failed moving %s to %s"
|
||||
msgstr "Falha ao mover %s para %s"
|
||||
|
||||
#. Error message
|
||||
#: sabnzbd/filesystem.py
|
||||
msgid "Blocked attempt to create directory %s"
|
||||
msgstr ""
|
||||
|
||||
#: sabnzbd/interface.py
|
||||
msgid "Refused connection from:"
|
||||
msgstr ""
|
||||
|
||||
#: sabnzbd/interface.py
|
||||
msgid "Refused connection with hostname \"%s\" from:"
|
||||
msgstr ""
|
||||
@@ -643,6 +652,7 @@ msgstr ""
|
||||
msgid "Authentication failed, check username/password."
|
||||
msgstr "Falha de autenticação, verifique usuário / senha."
|
||||
|
||||
#. Warning message
|
||||
#: sabnzbd/interface.py
|
||||
msgid "Unsuccessful login attempt from %s"
|
||||
msgstr ""
|
||||
@@ -3148,25 +3158,12 @@ msgstr "Gerar Nova Chave"
|
||||
msgid "API Key QR Code"
|
||||
msgstr "API Key QR Code"
|
||||
|
||||
#: sabnzbd/skintext.py
|
||||
msgid "List of local network ranges"
|
||||
msgstr "Lista de intervalos de rede local"
|
||||
|
||||
#: sabnzbd/skintext.py
|
||||
msgid ""
|
||||
"All local network addresses start with these prefixes (often \"192.168.1.\")"
|
||||
msgstr ""
|
||||
"Todas os endereços da rede local começam com esse prefixo (geralmente "
|
||||
"\"192.168.1.\")"
|
||||
|
||||
#: sabnzbd/skintext.py
|
||||
msgid "External internet access"
|
||||
msgstr "Acesso externo da Internet"
|
||||
|
||||
#: sabnzbd/skintext.py
|
||||
msgid ""
|
||||
"You can set access rights for systems outside your local network. Requires "
|
||||
"List of local network ranges to be defined."
|
||||
msgid "You can set access rights for systems outside your local network."
|
||||
msgstr ""
|
||||
|
||||
#: sabnzbd/skintext.py
|
||||
@@ -3484,19 +3481,26 @@ msgid "Action when unwanted extension detected"
|
||||
msgstr "Ação quando extensão indesejada for detectada"
|
||||
|
||||
#: sabnzbd/skintext.py
|
||||
msgid "Action when an unwanted extension is detected in RAR files"
|
||||
msgstr "Ação quando uma extensão indesejada é detectada em arquivos RAR"
|
||||
msgid "Action when an unwanted extension is detected"
|
||||
msgstr ""
|
||||
|
||||
#: sabnzbd/skintext.py
|
||||
msgid "Unwanted extensions"
|
||||
msgstr "Extensões indesejadas"
|
||||
|
||||
#: sabnzbd/skintext.py
|
||||
msgid ""
|
||||
"List all unwanted extensions. For example: <b>exe</b> or <b>exe, com</b>"
|
||||
msgid "Blacklist"
|
||||
msgstr ""
|
||||
|
||||
#: sabnzbd/skintext.py
|
||||
msgid "Whitelist"
|
||||
msgstr ""
|
||||
|
||||
#: sabnzbd/skintext.py
|
||||
msgid ""
|
||||
"Select a mode and list all (un)wanted extensions. For example: <b>exe</b> or"
|
||||
" <b>exe, com</b>"
|
||||
msgstr ""
|
||||
"Lista todas as extensões indesejadas. Por exemplo: <b>exe</b> ou <b>exe, "
|
||||
"com</b>"
|
||||
|
||||
#: sabnzbd/skintext.py
|
||||
msgid "Enable SFV-based checks"
|
||||
@@ -4042,6 +4046,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"
|
||||
@@ -4827,6 +4841,10 @@ msgstr "Esconder/Exibir arquivos completos"
|
||||
msgid "View Script Log"
|
||||
msgstr "Exibir Log do Script"
|
||||
|
||||
#: sabnzbd/skintext.py
|
||||
msgid "Renaming the job will abort Direct Unpack."
|
||||
msgstr ""
|
||||
|
||||
#: sabnzbd/skintext.py
|
||||
msgid ""
|
||||
"LocalStorage (cookies) are disabled in your browser, interface settings will"
|
||||
|
||||
@@ -8,7 +8,7 @@
|
||||
#
|
||||
msgid ""
|
||||
msgstr ""
|
||||
"Project-Id-Version: SABnzbd-3.2.0-develop\n"
|
||||
"Project-Id-Version: SABnzbd-3.3.0-develop\n"
|
||||
"PO-Revision-Date: 2020-06-27 15:49+0000\n"
|
||||
"Last-Translator: Eduard Baniceru <war4peace@gmail.com>, 2021\n"
|
||||
"Language-Team: Romanian (https://www.transifex.com/sabnzbd/teams/111101/ro/)\n"
|
||||
@@ -616,6 +616,15 @@ msgstr "Facere nereuşită (%s)"
|
||||
msgid "Failed moving %s to %s"
|
||||
msgstr "Mutare %s în %s nereuşită"
|
||||
|
||||
#. Error message
|
||||
#: sabnzbd/filesystem.py
|
||||
msgid "Blocked attempt to create directory %s"
|
||||
msgstr ""
|
||||
|
||||
#: sabnzbd/interface.py
|
||||
msgid "Refused connection from:"
|
||||
msgstr ""
|
||||
|
||||
#: sabnzbd/interface.py
|
||||
msgid "Refused connection with hostname \"%s\" from:"
|
||||
msgstr "Conectare refuzată cu gazda „%s” de la:"
|
||||
@@ -657,6 +666,7 @@ msgstr ""
|
||||
msgid "Authentication failed, check username/password."
|
||||
msgstr "Autentificare nereuşită, verifică nume utilizator/parolă."
|
||||
|
||||
#. Warning message
|
||||
#: sabnzbd/interface.py
|
||||
msgid "Unsuccessful login attempt from %s"
|
||||
msgstr "Încercare de conectare nereușită de la %s"
|
||||
@@ -3175,23 +3185,12 @@ msgstr "Generează o Cheie Nouă"
|
||||
msgid "API Key QR Code"
|
||||
msgstr "Cheie API sau Cod QR"
|
||||
|
||||
#: sabnzbd/skintext.py
|
||||
msgid "List of local network ranges"
|
||||
msgstr "Listă de rețele locale"
|
||||
|
||||
#: sabnzbd/skintext.py
|
||||
msgid ""
|
||||
"All local network addresses start with these prefixes (often \"192.168.1.\")"
|
||||
msgstr "Toate rețelele locale încep cu acest prefixe (de regulă \"192.168.1.\")"
|
||||
|
||||
#: sabnzbd/skintext.py
|
||||
msgid "External internet access"
|
||||
msgstr "Acces extern la internet"
|
||||
|
||||
#: sabnzbd/skintext.py
|
||||
msgid ""
|
||||
"You can set access rights for systems outside your local network. Requires "
|
||||
"List of local network ranges to be defined."
|
||||
msgid "You can set access rights for systems outside your local network."
|
||||
msgstr ""
|
||||
|
||||
#: sabnzbd/skintext.py
|
||||
@@ -3508,19 +3507,26 @@ msgid "Action when unwanted extension detected"
|
||||
msgstr "Acțiune când se detectează o extensie nedorită"
|
||||
|
||||
#: sabnzbd/skintext.py
|
||||
msgid "Action when an unwanted extension is detected in RAR files"
|
||||
msgstr "Acțiune când se detectează extensie nedorită într-un fișier RAR"
|
||||
msgid "Action when an unwanted extension is detected"
|
||||
msgstr ""
|
||||
|
||||
#: sabnzbd/skintext.py
|
||||
msgid "Unwanted extensions"
|
||||
msgstr "Extensii nedorite"
|
||||
|
||||
#: sabnzbd/skintext.py
|
||||
msgid ""
|
||||
"List all unwanted extensions. For example: <b>exe</b> or <b>exe, com</b>"
|
||||
msgid "Blacklist"
|
||||
msgstr ""
|
||||
|
||||
#: sabnzbd/skintext.py
|
||||
msgid "Whitelist"
|
||||
msgstr ""
|
||||
|
||||
#: sabnzbd/skintext.py
|
||||
msgid ""
|
||||
"Select a mode and list all (un)wanted extensions. For example: <b>exe</b> or"
|
||||
" <b>exe, com</b>"
|
||||
msgstr ""
|
||||
"Listă cu toate extensiile nedorite. De exemplu: <b>exe</b> or <b>exe, "
|
||||
"com</b>"
|
||||
|
||||
#: sabnzbd/skintext.py
|
||||
msgid "Enable SFV-based checks"
|
||||
@@ -4068,6 +4074,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"
|
||||
@@ -4851,6 +4867,10 @@ msgstr "Ascunde/arată fișierele finalizate"
|
||||
msgid "View Script Log"
|
||||
msgstr "Vezi Jurnal Script"
|
||||
|
||||
#: sabnzbd/skintext.py
|
||||
msgid "Renaming the job will abort Direct Unpack."
|
||||
msgstr ""
|
||||
|
||||
#: sabnzbd/skintext.py
|
||||
msgid ""
|
||||
"LocalStorage (cookies) are disabled in your browser, interface settings will"
|
||||
|
||||
@@ -7,7 +7,7 @@
|
||||
#
|
||||
msgid ""
|
||||
msgstr ""
|
||||
"Project-Id-Version: SABnzbd-3.2.0-develop\n"
|
||||
"Project-Id-Version: SABnzbd-3.3.0-develop\n"
|
||||
"PO-Revision-Date: 2020-06-27 15:49+0000\n"
|
||||
"Last-Translator: Safihre <safihre@sabnzbd.org>, 2020\n"
|
||||
"Language-Team: Russian (https://www.transifex.com/sabnzbd/teams/111101/ru/)\n"
|
||||
@@ -598,6 +598,15 @@ msgstr "Не удалось создать (%s)"
|
||||
msgid "Failed moving %s to %s"
|
||||
msgstr "Не удалось переместить %s в %s"
|
||||
|
||||
#. Error message
|
||||
#: sabnzbd/filesystem.py
|
||||
msgid "Blocked attempt to create directory %s"
|
||||
msgstr ""
|
||||
|
||||
#: sabnzbd/interface.py
|
||||
msgid "Refused connection from:"
|
||||
msgstr ""
|
||||
|
||||
#: sabnzbd/interface.py
|
||||
msgid "Refused connection with hostname \"%s\" from:"
|
||||
msgstr ""
|
||||
@@ -639,6 +648,7 @@ msgstr ""
|
||||
msgid "Authentication failed, check username/password."
|
||||
msgstr "Ошибка проверки подлинности. Проверьте имя и пароль."
|
||||
|
||||
#. Warning message
|
||||
#: sabnzbd/interface.py
|
||||
msgid "Unsuccessful login attempt from %s"
|
||||
msgstr ""
|
||||
@@ -3141,23 +3151,12 @@ msgstr "Создать новый ключ"
|
||||
msgid "API Key QR Code"
|
||||
msgstr "QR-код ключа API"
|
||||
|
||||
#: sabnzbd/skintext.py
|
||||
msgid "List of local network ranges"
|
||||
msgstr ""
|
||||
|
||||
#: sabnzbd/skintext.py
|
||||
msgid ""
|
||||
"All local network addresses start with these prefixes (often \"192.168.1.\")"
|
||||
msgstr ""
|
||||
|
||||
#: sabnzbd/skintext.py
|
||||
msgid "External internet access"
|
||||
msgstr ""
|
||||
|
||||
#: sabnzbd/skintext.py
|
||||
msgid ""
|
||||
"You can set access rights for systems outside your local network. Requires "
|
||||
"List of local network ranges to be defined."
|
||||
msgid "You can set access rights for systems outside your local network."
|
||||
msgstr ""
|
||||
|
||||
#: sabnzbd/skintext.py
|
||||
@@ -3476,16 +3475,25 @@ msgid "Action when unwanted extension detected"
|
||||
msgstr ""
|
||||
|
||||
#: sabnzbd/skintext.py
|
||||
msgid "Action when an unwanted extension is detected in RAR files"
|
||||
msgid "Action when an unwanted extension is detected"
|
||||
msgstr ""
|
||||
|
||||
#: sabnzbd/skintext.py
|
||||
msgid "Unwanted extensions"
|
||||
msgstr ""
|
||||
|
||||
#: sabnzbd/skintext.py
|
||||
msgid "Blacklist"
|
||||
msgstr ""
|
||||
|
||||
#: sabnzbd/skintext.py
|
||||
msgid "Whitelist"
|
||||
msgstr ""
|
||||
|
||||
#: sabnzbd/skintext.py
|
||||
msgid ""
|
||||
"List all unwanted extensions. For example: <b>exe</b> or <b>exe, com</b>"
|
||||
"Select a mode and list all (un)wanted extensions. For example: <b>exe</b> or"
|
||||
" <b>exe, com</b>"
|
||||
msgstr ""
|
||||
|
||||
#: sabnzbd/skintext.py
|
||||
@@ -4027,6 +4035,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"
|
||||
@@ -4817,6 +4835,10 @@ msgstr ""
|
||||
msgid "View Script Log"
|
||||
msgstr "Просмотреть журнал сценария"
|
||||
|
||||
#: sabnzbd/skintext.py
|
||||
msgid "Renaming the job will abort Direct Unpack."
|
||||
msgstr ""
|
||||
|
||||
#: sabnzbd/skintext.py
|
||||
msgid ""
|
||||
"LocalStorage (cookies) are disabled in your browser, interface settings will"
|
||||
|
||||
@@ -7,7 +7,7 @@
|
||||
#
|
||||
msgid ""
|
||||
msgstr ""
|
||||
"Project-Id-Version: SABnzbd-3.2.0-develop\n"
|
||||
"Project-Id-Version: SABnzbd-3.3.0-develop\n"
|
||||
"PO-Revision-Date: 2020-06-27 15:49+0000\n"
|
||||
"Last-Translator: Safihre <safihre@sabnzbd.org>, 2020\n"
|
||||
"Language-Team: Serbian (https://www.transifex.com/sabnzbd/teams/111101/sr/)\n"
|
||||
@@ -597,6 +597,15 @@ msgstr "Neuspešno kreiranje (%s)"
|
||||
msgid "Failed moving %s to %s"
|
||||
msgstr "Neuspešno premeštanje %s u %s"
|
||||
|
||||
#. Error message
|
||||
#: sabnzbd/filesystem.py
|
||||
msgid "Blocked attempt to create directory %s"
|
||||
msgstr ""
|
||||
|
||||
#: sabnzbd/interface.py
|
||||
msgid "Refused connection from:"
|
||||
msgstr ""
|
||||
|
||||
#: sabnzbd/interface.py
|
||||
msgid "Refused connection with hostname \"%s\" from:"
|
||||
msgstr ""
|
||||
@@ -636,6 +645,7 @@ msgstr ""
|
||||
msgid "Authentication failed, check username/password."
|
||||
msgstr "Аутентификација погрешна, проверити име/лозинку."
|
||||
|
||||
#. Warning message
|
||||
#: sabnzbd/interface.py
|
||||
msgid "Unsuccessful login attempt from %s"
|
||||
msgstr ""
|
||||
@@ -3128,25 +3138,12 @@ msgstr "Генериши нов кључ"
|
||||
msgid "API Key QR Code"
|
||||
msgstr "QR Код АПИ кључа"
|
||||
|
||||
#: sabnzbd/skintext.py
|
||||
msgid "List of local network ranges"
|
||||
msgstr "Lista lokalnih mrežnih raspona"
|
||||
|
||||
#: sabnzbd/skintext.py
|
||||
msgid ""
|
||||
"All local network addresses start with these prefixes (often \"192.168.1.\")"
|
||||
msgstr ""
|
||||
"Sve lokalne mrežne adrese počinju sa sledećim prefiksima (najčešće "
|
||||
"\"192.168.1.\")"
|
||||
|
||||
#: sabnzbd/skintext.py
|
||||
msgid "External internet access"
|
||||
msgstr "Екстерни приступ интернету"
|
||||
|
||||
#: sabnzbd/skintext.py
|
||||
msgid ""
|
||||
"You can set access rights for systems outside your local network. Requires "
|
||||
"List of local network ranges to be defined."
|
||||
msgid "You can set access rights for systems outside your local network."
|
||||
msgstr ""
|
||||
|
||||
#: sabnzbd/skintext.py
|
||||
@@ -3464,18 +3461,26 @@ msgid "Action when unwanted extension detected"
|
||||
msgstr "Radnja kada je otkrivena neželjena ekstenzija"
|
||||
|
||||
#: sabnzbd/skintext.py
|
||||
msgid "Action when an unwanted extension is detected in RAR files"
|
||||
msgstr "Radnja kada je otkrivena neželjena ekstenzija u RAR datotekama"
|
||||
msgid "Action when an unwanted extension is detected"
|
||||
msgstr ""
|
||||
|
||||
#: sabnzbd/skintext.py
|
||||
msgid "Unwanted extensions"
|
||||
msgstr "Neželjene ekstenzije"
|
||||
|
||||
#: sabnzbd/skintext.py
|
||||
msgid ""
|
||||
"List all unwanted extensions. For example: <b>exe</b> or <b>exe, com</b>"
|
||||
msgid "Blacklist"
|
||||
msgstr ""
|
||||
|
||||
#: sabnzbd/skintext.py
|
||||
msgid "Whitelist"
|
||||
msgstr ""
|
||||
|
||||
#: sabnzbd/skintext.py
|
||||
msgid ""
|
||||
"Select a mode and list all (un)wanted extensions. For example: <b>exe</b> or"
|
||||
" <b>exe, com</b>"
|
||||
msgstr ""
|
||||
"Lista svih neželjenih ekstenzija. Na primer: <b>exe</b> or <b>exe, com</b>"
|
||||
|
||||
#: sabnzbd/skintext.py
|
||||
msgid "Enable SFV-based checks"
|
||||
@@ -4015,6 +4020,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"
|
||||
@@ -4799,6 +4814,10 @@ msgstr "Sakrij/prikaži sve završene datoteke"
|
||||
msgid "View Script Log"
|
||||
msgstr "Види извештај скрипта"
|
||||
|
||||
#: sabnzbd/skintext.py
|
||||
msgid "Renaming the job will abort Direct Unpack."
|
||||
msgstr ""
|
||||
|
||||
#: sabnzbd/skintext.py
|
||||
msgid ""
|
||||
"LocalStorage (cookies) are disabled in your browser, interface settings will"
|
||||
|
||||
@@ -7,7 +7,7 @@
|
||||
#
|
||||
msgid ""
|
||||
msgstr ""
|
||||
"Project-Id-Version: SABnzbd-3.2.0-develop\n"
|
||||
"Project-Id-Version: SABnzbd-3.3.0-develop\n"
|
||||
"PO-Revision-Date: 2020-06-27 15:49+0000\n"
|
||||
"Last-Translator: Safihre <safihre@sabnzbd.org>, 2020\n"
|
||||
"Language-Team: Swedish (https://www.transifex.com/sabnzbd/teams/111101/sv/)\n"
|
||||
@@ -597,6 +597,15 @@ msgstr "Skapande av (%s) misslyckades"
|
||||
msgid "Failed moving %s to %s"
|
||||
msgstr "Det gick inte att flyta %s till %s"
|
||||
|
||||
#. Error message
|
||||
#: sabnzbd/filesystem.py
|
||||
msgid "Blocked attempt to create directory %s"
|
||||
msgstr ""
|
||||
|
||||
#: sabnzbd/interface.py
|
||||
msgid "Refused connection from:"
|
||||
msgstr ""
|
||||
|
||||
#: sabnzbd/interface.py
|
||||
msgid "Refused connection with hostname \"%s\" from:"
|
||||
msgstr ""
|
||||
@@ -638,6 +647,7 @@ msgstr ""
|
||||
msgid "Authentication failed, check username/password."
|
||||
msgstr "Autentisering misslyckades, kontrollera användarnamn och lösenord."
|
||||
|
||||
#. Warning message
|
||||
#: sabnzbd/interface.py
|
||||
msgid "Unsuccessful login attempt from %s"
|
||||
msgstr ""
|
||||
@@ -3139,25 +3149,12 @@ msgstr "Generera Ny Nyckel"
|
||||
msgid "API Key QR Code"
|
||||
msgstr "API- eller QR-kod"
|
||||
|
||||
#: sabnzbd/skintext.py
|
||||
msgid "List of local network ranges"
|
||||
msgstr "Lista av lokala nätverksomfång"
|
||||
|
||||
#: sabnzbd/skintext.py
|
||||
msgid ""
|
||||
"All local network addresses start with these prefixes (often \"192.168.1.\")"
|
||||
msgstr ""
|
||||
"Alla lokala nätverksadresser startar med dessa prefixer (ofta "
|
||||
"\"192.168.1.\")"
|
||||
|
||||
#: sabnzbd/skintext.py
|
||||
msgid "External internet access"
|
||||
msgstr "Extern internetåtkomst"
|
||||
|
||||
#: sabnzbd/skintext.py
|
||||
msgid ""
|
||||
"You can set access rights for systems outside your local network. Requires "
|
||||
"List of local network ranges to be defined."
|
||||
msgid "You can set access rights for systems outside your local network."
|
||||
msgstr ""
|
||||
|
||||
#: sabnzbd/skintext.py
|
||||
@@ -3473,18 +3470,26 @@ msgid "Action when unwanted extension detected"
|
||||
msgstr "Händelse när oönskad filändelse hittad"
|
||||
|
||||
#: sabnzbd/skintext.py
|
||||
msgid "Action when an unwanted extension is detected in RAR files"
|
||||
msgstr "Händelse när en oönskad filändelse är hittad i RAR-filer."
|
||||
msgid "Action when an unwanted extension is detected"
|
||||
msgstr ""
|
||||
|
||||
#: sabnzbd/skintext.py
|
||||
msgid "Unwanted extensions"
|
||||
msgstr "Oönskade filändelser"
|
||||
|
||||
#: sabnzbd/skintext.py
|
||||
msgid ""
|
||||
"List all unwanted extensions. For example: <b>exe</b> or <b>exe, com</b>"
|
||||
msgid "Blacklist"
|
||||
msgstr ""
|
||||
|
||||
#: sabnzbd/skintext.py
|
||||
msgid "Whitelist"
|
||||
msgstr ""
|
||||
|
||||
#: sabnzbd/skintext.py
|
||||
msgid ""
|
||||
"Select a mode and list all (un)wanted extensions. For example: <b>exe</b> or"
|
||||
" <b>exe, com</b>"
|
||||
msgstr ""
|
||||
"Lista alla oönskade filändelser. Till Exempel: <b>exe</b> or <b>exe, com</b>"
|
||||
|
||||
#: sabnzbd/skintext.py
|
||||
msgid "Enable SFV-based checks"
|
||||
@@ -4028,6 +4033,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"
|
||||
@@ -4811,6 +4826,10 @@ msgstr "Visa/göm färdiga filer"
|
||||
msgid "View Script Log"
|
||||
msgstr "Visa skriptlogg"
|
||||
|
||||
#: sabnzbd/skintext.py
|
||||
msgid "Renaming the job will abort Direct Unpack."
|
||||
msgstr ""
|
||||
|
||||
#: sabnzbd/skintext.py
|
||||
msgid ""
|
||||
"LocalStorage (cookies) are disabled in your browser, interface settings will"
|
||||
|
||||
@@ -7,7 +7,7 @@
|
||||
#
|
||||
msgid ""
|
||||
msgstr ""
|
||||
"Project-Id-Version: SABnzbd-3.2.0-develop\n"
|
||||
"Project-Id-Version: SABnzbd-3.3.0-develop\n"
|
||||
"PO-Revision-Date: 2020-06-27 15:49+0000\n"
|
||||
"Last-Translator: Safihre <safihre@sabnzbd.org>, 2020\n"
|
||||
"Language-Team: Chinese (China) (https://www.transifex.com/sabnzbd/teams/111101/zh_CN/)\n"
|
||||
@@ -594,6 +594,15 @@ msgstr "创建失败 (%s)"
|
||||
msgid "Failed moving %s to %s"
|
||||
msgstr "将 %s 移动到 %s 失败"
|
||||
|
||||
#. Error message
|
||||
#: sabnzbd/filesystem.py
|
||||
msgid "Blocked attempt to create directory %s"
|
||||
msgstr ""
|
||||
|
||||
#: sabnzbd/interface.py
|
||||
msgid "Refused connection from:"
|
||||
msgstr ""
|
||||
|
||||
#: sabnzbd/interface.py
|
||||
msgid "Refused connection with hostname \"%s\" from:"
|
||||
msgstr ""
|
||||
@@ -629,6 +638,7 @@ msgstr "缺身份认证信息,请在第三方程序中输入“配置”->“
|
||||
msgid "Authentication failed, check username/password."
|
||||
msgstr "身份认证失败,请检查用户名/密码。"
|
||||
|
||||
#. Warning message
|
||||
#: sabnzbd/interface.py
|
||||
msgid "Unsuccessful login attempt from %s"
|
||||
msgstr "%s 中有失败的登陆请求"
|
||||
@@ -3107,24 +3117,13 @@ msgstr "生成新的 Key"
|
||||
msgid "API Key QR Code"
|
||||
msgstr "API Key QR 码"
|
||||
|
||||
#: sabnzbd/skintext.py
|
||||
msgid "List of local network ranges"
|
||||
msgstr "本地网段列表"
|
||||
|
||||
#: sabnzbd/skintext.py
|
||||
msgid ""
|
||||
"All local network addresses start with these prefixes (often \"192.168.1.\")"
|
||||
msgstr "本地网络地址以这些前缀开头 (通常为“192.168.1.”)"
|
||||
|
||||
#: sabnzbd/skintext.py
|
||||
msgid "External internet access"
|
||||
msgstr "外部互联网访问"
|
||||
|
||||
#: sabnzbd/skintext.py
|
||||
msgid ""
|
||||
"You can set access rights for systems outside your local network. Requires "
|
||||
"List of local network ranges to be defined."
|
||||
msgstr "您可以设定非本地网络的访问权限。要求定义本地网络列表。"
|
||||
msgid "You can set access rights for systems outside your local network."
|
||||
msgstr ""
|
||||
|
||||
#: sabnzbd/skintext.py
|
||||
msgid "No access"
|
||||
@@ -3420,17 +3419,26 @@ msgid "Action when unwanted extension detected"
|
||||
msgstr "侦测到不需要的扩展名时的操作"
|
||||
|
||||
#: sabnzbd/skintext.py
|
||||
msgid "Action when an unwanted extension is detected in RAR files"
|
||||
msgstr "RAR 文件中侦测到不需要的扩展名时的操作"
|
||||
msgid "Action when an unwanted extension is detected"
|
||||
msgstr ""
|
||||
|
||||
#: sabnzbd/skintext.py
|
||||
msgid "Unwanted extensions"
|
||||
msgstr "不需要的扩展名"
|
||||
|
||||
#: sabnzbd/skintext.py
|
||||
msgid "Blacklist"
|
||||
msgstr ""
|
||||
|
||||
#: sabnzbd/skintext.py
|
||||
msgid "Whitelist"
|
||||
msgstr ""
|
||||
|
||||
#: sabnzbd/skintext.py
|
||||
msgid ""
|
||||
"List all unwanted extensions. For example: <b>exe</b> or <b>exe, com</b>"
|
||||
msgstr "所有不需要扩展名的列表。例如: <b>exe</b> 或 <b>exe, com</b>"
|
||||
"Select a mode and list all (un)wanted extensions. For example: <b>exe</b> or"
|
||||
" <b>exe, com</b>"
|
||||
msgstr ""
|
||||
|
||||
#: sabnzbd/skintext.py
|
||||
msgid "Enable SFV-based checks"
|
||||
@@ -3960,6 +3968,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"
|
||||
@@ -4742,6 +4760,10 @@ msgstr "隐藏/显示已完成文件"
|
||||
msgid "View Script Log"
|
||||
msgstr "查看脚本日志"
|
||||
|
||||
#: sabnzbd/skintext.py
|
||||
msgid "Renaming the job will abort Direct Unpack."
|
||||
msgstr ""
|
||||
|
||||
#: sabnzbd/skintext.py
|
||||
msgid ""
|
||||
"LocalStorage (cookies) are disabled in your browser, interface settings will"
|
||||
|
||||
@@ -5,7 +5,7 @@
|
||||
#
|
||||
msgid ""
|
||||
msgstr ""
|
||||
"Project-Id-Version: SABnzbd-3.2.0-develop\n"
|
||||
"Project-Id-Version: SABnzbd-3.3.0-develop\n"
|
||||
"PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n"
|
||||
"Last-Translator: team@sabnzbd.org\n"
|
||||
"Language-Team: SABnzbd <team@sabnzbd.org>\n"
|
||||
|
||||
@@ -4,7 +4,7 @@
|
||||
#
|
||||
msgid ""
|
||||
msgstr ""
|
||||
"Project-Id-Version: SABnzbd-3.2.0-develop\n"
|
||||
"Project-Id-Version: SABnzbd-3.3.0-develop\n"
|
||||
"PO-Revision-Date: 2020-06-27 15:56+0000\n"
|
||||
"Language-Team: Czech (https://www.transifex.com/sabnzbd/teams/111101/cs/)\n"
|
||||
"MIME-Version: 1.0\n"
|
||||
|
||||
@@ -7,7 +7,7 @@
|
||||
#
|
||||
msgid ""
|
||||
msgstr ""
|
||||
"Project-Id-Version: SABnzbd-3.2.0-develop\n"
|
||||
"Project-Id-Version: SABnzbd-3.3.0-develop\n"
|
||||
"PO-Revision-Date: 2020-06-27 15:56+0000\n"
|
||||
"Last-Translator: Safihre <safihre@sabnzbd.org>, 2020\n"
|
||||
"Language-Team: Danish (https://www.transifex.com/sabnzbd/teams/111101/da/)\n"
|
||||
|
||||
@@ -7,7 +7,7 @@
|
||||
#
|
||||
msgid ""
|
||||
msgstr ""
|
||||
"Project-Id-Version: SABnzbd-3.2.0-develop\n"
|
||||
"Project-Id-Version: SABnzbd-3.3.0-develop\n"
|
||||
"PO-Revision-Date: 2020-06-27 15:56+0000\n"
|
||||
"Last-Translator: Safihre <safihre@sabnzbd.org>, 2020\n"
|
||||
"Language-Team: German (https://www.transifex.com/sabnzbd/teams/111101/de/)\n"
|
||||
|
||||
@@ -8,7 +8,7 @@
|
||||
#
|
||||
msgid ""
|
||||
msgstr ""
|
||||
"Project-Id-Version: SABnzbd-3.2.0-develop\n"
|
||||
"Project-Id-Version: SABnzbd-3.3.0-develop\n"
|
||||
"PO-Revision-Date: 2020-06-27 15:56+0000\n"
|
||||
"Last-Translator: Ester Molla Aragones <moarages@gmail.com>, 2020\n"
|
||||
"Language-Team: Spanish (https://www.transifex.com/sabnzbd/teams/111101/es/)\n"
|
||||
|
||||
@@ -7,7 +7,7 @@
|
||||
#
|
||||
msgid ""
|
||||
msgstr ""
|
||||
"Project-Id-Version: SABnzbd-3.2.0-develop\n"
|
||||
"Project-Id-Version: SABnzbd-3.3.0-develop\n"
|
||||
"PO-Revision-Date: 2020-06-27 15:56+0000\n"
|
||||
"Last-Translator: Safihre <safihre@sabnzbd.org>, 2020\n"
|
||||
"Language-Team: Finnish (https://www.transifex.com/sabnzbd/teams/111101/fi/)\n"
|
||||
|
||||
@@ -8,7 +8,7 @@
|
||||
#
|
||||
msgid ""
|
||||
msgstr ""
|
||||
"Project-Id-Version: SABnzbd-3.2.0-develop\n"
|
||||
"Project-Id-Version: SABnzbd-3.3.0-develop\n"
|
||||
"PO-Revision-Date: 2020-06-27 15:56+0000\n"
|
||||
"Last-Translator: Fred L <88com88@gmail.com>, 2021\n"
|
||||
"Language-Team: French (https://www.transifex.com/sabnzbd/teams/111101/fr/)\n"
|
||||
|
||||
@@ -8,7 +8,7 @@
|
||||
#
|
||||
msgid ""
|
||||
msgstr ""
|
||||
"Project-Id-Version: SABnzbd-3.2.0-develop\n"
|
||||
"Project-Id-Version: SABnzbd-3.3.0-develop\n"
|
||||
"PO-Revision-Date: 2020-06-27 15:56+0000\n"
|
||||
"Last-Translator: ION, 2021\n"
|
||||
"Language-Team: Hebrew (https://www.transifex.com/sabnzbd/teams/111101/he/)\n"
|
||||
@@ -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 "ההגדרות והנתונים שלך ישתמרו."
|
||||
|
||||
@@ -7,7 +7,7 @@
|
||||
#
|
||||
msgid ""
|
||||
msgstr ""
|
||||
"Project-Id-Version: SABnzbd-3.2.0-develop\n"
|
||||
"Project-Id-Version: SABnzbd-3.3.0-develop\n"
|
||||
"PO-Revision-Date: 2020-06-27 15:56+0000\n"
|
||||
"Last-Translator: Safihre <safihre@sabnzbd.org>, 2020\n"
|
||||
"Language-Team: Norwegian Bokmål (https://www.transifex.com/sabnzbd/teams/111101/nb/)\n"
|
||||
|
||||
@@ -7,7 +7,7 @@
|
||||
#
|
||||
msgid ""
|
||||
msgstr ""
|
||||
"Project-Id-Version: SABnzbd-3.2.0-develop\n"
|
||||
"Project-Id-Version: SABnzbd-3.3.0-develop\n"
|
||||
"PO-Revision-Date: 2020-06-27 15:56+0000\n"
|
||||
"Last-Translator: Safihre <safihre@sabnzbd.org>, 2021\n"
|
||||
"Language-Team: Dutch (https://www.transifex.com/sabnzbd/teams/111101/nl/)\n"
|
||||
|
||||
@@ -7,7 +7,7 @@
|
||||
#
|
||||
msgid ""
|
||||
msgstr ""
|
||||
"Project-Id-Version: SABnzbd-3.2.0-develop\n"
|
||||
"Project-Id-Version: SABnzbd-3.3.0-develop\n"
|
||||
"PO-Revision-Date: 2020-06-27 15:56+0000\n"
|
||||
"Last-Translator: Safihre <safihre@sabnzbd.org>, 2020\n"
|
||||
"Language-Team: Polish (https://www.transifex.com/sabnzbd/teams/111101/pl/)\n"
|
||||
|
||||
@@ -7,7 +7,7 @@
|
||||
#
|
||||
msgid ""
|
||||
msgstr ""
|
||||
"Project-Id-Version: SABnzbd-3.2.0-develop\n"
|
||||
"Project-Id-Version: SABnzbd-3.3.0-develop\n"
|
||||
"PO-Revision-Date: 2020-06-27 15:56+0000\n"
|
||||
"Last-Translator: Safihre <safihre@sabnzbd.org>, 2020\n"
|
||||
"Language-Team: Portuguese (Brazil) (https://www.transifex.com/sabnzbd/teams/111101/pt_BR/)\n"
|
||||
|
||||
@@ -7,7 +7,7 @@
|
||||
#
|
||||
msgid ""
|
||||
msgstr ""
|
||||
"Project-Id-Version: SABnzbd-3.2.0-develop\n"
|
||||
"Project-Id-Version: SABnzbd-3.3.0-develop\n"
|
||||
"PO-Revision-Date: 2020-06-27 15:56+0000\n"
|
||||
"Last-Translator: Safihre <safihre@sabnzbd.org>, 2020\n"
|
||||
"Language-Team: Romanian (https://www.transifex.com/sabnzbd/teams/111101/ro/)\n"
|
||||
|
||||
@@ -7,7 +7,7 @@
|
||||
#
|
||||
msgid ""
|
||||
msgstr ""
|
||||
"Project-Id-Version: SABnzbd-3.2.0-develop\n"
|
||||
"Project-Id-Version: SABnzbd-3.3.0-develop\n"
|
||||
"PO-Revision-Date: 2020-06-27 15:56+0000\n"
|
||||
"Last-Translator: Safihre <safihre@sabnzbd.org>, 2020\n"
|
||||
"Language-Team: Russian (https://www.transifex.com/sabnzbd/teams/111101/ru/)\n"
|
||||
|
||||
@@ -7,7 +7,7 @@
|
||||
#
|
||||
msgid ""
|
||||
msgstr ""
|
||||
"Project-Id-Version: SABnzbd-3.2.0-develop\n"
|
||||
"Project-Id-Version: SABnzbd-3.3.0-develop\n"
|
||||
"PO-Revision-Date: 2020-06-27 15:56+0000\n"
|
||||
"Last-Translator: Safihre <safihre@sabnzbd.org>, 2020\n"
|
||||
"Language-Team: Serbian (https://www.transifex.com/sabnzbd/teams/111101/sr/)\n"
|
||||
|
||||
@@ -7,7 +7,7 @@
|
||||
#
|
||||
msgid ""
|
||||
msgstr ""
|
||||
"Project-Id-Version: SABnzbd-3.2.0-develop\n"
|
||||
"Project-Id-Version: SABnzbd-3.3.0-develop\n"
|
||||
"PO-Revision-Date: 2020-06-27 15:56+0000\n"
|
||||
"Last-Translator: Safihre <safihre@sabnzbd.org>, 2020\n"
|
||||
"Language-Team: Swedish (https://www.transifex.com/sabnzbd/teams/111101/sv/)\n"
|
||||
|
||||
@@ -7,7 +7,7 @@
|
||||
#
|
||||
msgid ""
|
||||
msgstr ""
|
||||
"Project-Id-Version: SABnzbd-3.2.0-develop\n"
|
||||
"Project-Id-Version: SABnzbd-3.3.0-develop\n"
|
||||
"PO-Revision-Date: 2020-06-27 15:56+0000\n"
|
||||
"Last-Translator: Safihre <safihre@sabnzbd.org>, 2020\n"
|
||||
"Language-Team: Chinese (China) (https://www.transifex.com/sabnzbd/teams/111101/zh_CN/)\n"
|
||||
|
||||
@@ -21,6 +21,7 @@ import datetime
|
||||
import tempfile
|
||||
import pickle
|
||||
import ctypes
|
||||
import ctypes.util
|
||||
import gzip
|
||||
import time
|
||||
import socket
|
||||
@@ -35,7 +36,7 @@ from typing import Any, AnyStr
|
||||
# Determine platform flags
|
||||
##############################################################################
|
||||
WIN32 = DARWIN = FOUNDATION = WIN64 = DOCKER = False
|
||||
KERNEL32 = LIBC = None
|
||||
KERNEL32 = LIBC = MACOSLIBC = None
|
||||
|
||||
if os.name == "nt":
|
||||
WIN32 = True
|
||||
@@ -56,10 +57,13 @@ elif os.name == "posix":
|
||||
except:
|
||||
pass
|
||||
|
||||
# See if we have Linux memory functions
|
||||
# See if we have the GNU glibc malloc_trim() memory release function
|
||||
try:
|
||||
LIBC = ctypes.CDLL("libc.so.6")
|
||||
LIBC.malloc_trim(0) # try the malloc_trim() call, which is a GNU extension
|
||||
except:
|
||||
# No malloc_trim(), probably because no glibc
|
||||
LIBC = None
|
||||
pass
|
||||
|
||||
# Parse macOS version numbers
|
||||
@@ -67,6 +71,7 @@ elif os.name == "posix":
|
||||
DARWIN = True
|
||||
# 12 = Sierra, 11 = ElCaptain, 10 = Yosemite, 9 = Mavericks, 8 = MountainLion
|
||||
DARWIN_VERSION = int(platform.mac_ver()[0].split(".")[1])
|
||||
MACOSLIBC = ctypes.CDLL(ctypes.util.find_library("c"), use_errno=True) # the MacOS C library
|
||||
try:
|
||||
import Foundation
|
||||
import sabnzbd.utils.sleepless as sleepless
|
||||
@@ -75,6 +80,7 @@ elif os.name == "posix":
|
||||
except:
|
||||
pass
|
||||
|
||||
|
||||
# Imported to be referenced from other files directly
|
||||
from sabnzbd.version import __version__, __baseline__
|
||||
|
||||
|
||||
@@ -29,7 +29,7 @@ import json
|
||||
import cherrypy
|
||||
import locale
|
||||
from threading import Thread
|
||||
from typing import List, Tuple
|
||||
from typing import Tuple
|
||||
|
||||
import sabnzbd
|
||||
from sabnzbd.constants import (
|
||||
@@ -59,10 +59,11 @@ from sabnzbd.misc import (
|
||||
opts_to_pp,
|
||||
)
|
||||
from sabnzbd.filesystem import diskspace, get_ext, clip_path, remove_all, list_scripts
|
||||
from sabnzbd.encoding import xml_name
|
||||
from sabnzbd.encoding import xml_name, utob
|
||||
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
|
||||
@@ -86,25 +87,6 @@ _MSG_BAD_SERVER_PARMS = "Incorrect server settings"
|
||||
|
||||
def api_handler(kwargs):
|
||||
""" API Dispatcher """
|
||||
if cfg.api_logging():
|
||||
# Was it proxy forwarded?
|
||||
xff = cherrypy.request.headers.get("X-Forwarded-For")
|
||||
if xff:
|
||||
logging.debug(
|
||||
"API-call from %s (X-Forwarded-For: %s) [%s] %s",
|
||||
cherrypy.request.remote.ip,
|
||||
xff,
|
||||
cherrypy.request.headers.get("User-Agent", "??"),
|
||||
kwargs,
|
||||
)
|
||||
else:
|
||||
logging.debug(
|
||||
"API-call from %s [%s] %s",
|
||||
cherrypy.request.remote.ip,
|
||||
cherrypy.request.headers.get("User-Agent", "??"),
|
||||
kwargs,
|
||||
)
|
||||
|
||||
# Clean-up the arguments
|
||||
for vr in ("mode", "output", "name"):
|
||||
if vr in kwargs and isinstance(kwargs[vr], list):
|
||||
@@ -114,11 +96,6 @@ def api_handler(kwargs):
|
||||
output = kwargs.get("output", "")
|
||||
name = kwargs.get("name", "")
|
||||
|
||||
if mode not in ("version", "auth"):
|
||||
msg = sabnzbd.interface.check_apikey(kwargs)
|
||||
if msg:
|
||||
return report(output, msg)
|
||||
|
||||
response = _api_table.get(mode, (_api_undefined, 2))[0](name, output, kwargs)
|
||||
return response
|
||||
|
||||
@@ -944,27 +921,27 @@ _api_table = {
|
||||
"version": (_api_version, 1),
|
||||
"auth": (_api_auth, 1),
|
||||
"restart": (_api_restart, 3),
|
||||
"restart_repair": (_api_restart_repair, 2),
|
||||
"restart_repair": (_api_restart_repair, 3),
|
||||
"disconnect": (_api_disconnect, 2),
|
||||
"osx_icon": (_api_osx_icon, 3),
|
||||
"gc_stats": (_api_gc_stats, 3),
|
||||
"rescan": (_api_rescan, 2),
|
||||
"eval_sort": (_api_eval_sort, 2),
|
||||
"eval_sort": (_api_eval_sort, 3),
|
||||
"watched_now": (_api_watched_now, 2),
|
||||
"resume_pp": (_api_resume_pp, 2),
|
||||
"pause_pp": (_api_pause_pp, 2),
|
||||
"rss_now": (_api_rss_now, 2),
|
||||
"browse": (_api_browse, 2),
|
||||
"browse": (_api_browse, 3),
|
||||
"retry_all": (_api_retry_all, 2),
|
||||
"reset_quota": (_api_reset_quota, 2),
|
||||
"test_email": (_api_test_email, 2),
|
||||
"test_windows": (_api_test_windows, 2),
|
||||
"test_notif": (_api_test_notif, 2),
|
||||
"test_osd": (_api_test_osd, 2),
|
||||
"test_pushover": (_api_test_pushover, 2),
|
||||
"test_pushbullet": (_api_test_pushbullet, 2),
|
||||
"test_prowl": (_api_test_prowl, 2),
|
||||
"test_nscript": (_api_test_nscript, 2),
|
||||
"reset_quota": (_api_reset_quota, 3),
|
||||
"test_email": (_api_test_email, 3),
|
||||
"test_windows": (_api_test_windows, 3),
|
||||
"test_notif": (_api_test_notif, 3),
|
||||
"test_osd": (_api_test_osd, 3),
|
||||
"test_pushover": (_api_test_pushover, 3),
|
||||
"test_pushbullet": (_api_test_pushbullet, 3),
|
||||
"test_prowl": (_api_test_prowl, 3),
|
||||
"test_nscript": (_api_test_nscript, 3),
|
||||
}
|
||||
|
||||
_api_queue_table = {
|
||||
@@ -984,23 +961,24 @@ _api_config_table = {
|
||||
"speedlimit": (_api_config_speedlimit, 2),
|
||||
"set_speedlimit": (_api_config_speedlimit, 2),
|
||||
"get_speedlimit": (_api_config_get_speedlimit, 2),
|
||||
"set_colorscheme": (_api_config_set_colorscheme, 2),
|
||||
"set_pause": (_api_config_set_pause, 2),
|
||||
"set_colorscheme": (_api_config_set_colorscheme, 3),
|
||||
"set_apikey": (_api_config_set_apikey, 3),
|
||||
"set_nzbkey": (_api_config_set_nzbkey, 3),
|
||||
"regenerate_certs": (_api_config_regenerate_certs, 3),
|
||||
"test_server": (_api_config_test_server, 2),
|
||||
"test_server": (_api_config_test_server, 3),
|
||||
}
|
||||
|
||||
|
||||
def api_level(cmd, name):
|
||||
def api_level(mode: str, name: str) -> int:
|
||||
""" Return access level required for this API call """
|
||||
if cmd in _api_table:
|
||||
return _api_table[cmd][1]
|
||||
if name == "queue" and cmd in _api_queue_table:
|
||||
return _api_queue_table[cmd][1]
|
||||
if name == "config" and cmd in _api_config_table:
|
||||
return _api_config_table[cmd][1]
|
||||
if mode == "queue" and name in _api_queue_table:
|
||||
return _api_queue_table[name][1]
|
||||
if mode == "config" and name in _api_config_table:
|
||||
return _api_config_table[name][1]
|
||||
if mode in _api_table:
|
||||
return _api_table[mode][1]
|
||||
# It is invalid if it's none of these, but that's is handled somewhere else
|
||||
return 4
|
||||
|
||||
|
||||
@@ -1021,7 +999,7 @@ def report(output, error=None, keyword="value", data=None):
|
||||
info = data
|
||||
else:
|
||||
info = {keyword: data}
|
||||
response = json.dumps(info).encode("utf-8")
|
||||
response = utob(json.dumps(info))
|
||||
|
||||
elif output == "xml":
|
||||
if not keyword:
|
||||
@@ -1600,6 +1578,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)
|
||||
|
||||
@@ -30,7 +30,15 @@ from typing import Tuple, Optional, List
|
||||
|
||||
import sabnzbd
|
||||
from sabnzbd.misc import get_all_passwords, match_str
|
||||
from sabnzbd.filesystem import set_permissions, clip_path, has_win_device, diskspace, get_filename, get_ext
|
||||
from sabnzbd.filesystem import (
|
||||
set_permissions,
|
||||
clip_path,
|
||||
has_win_device,
|
||||
diskspace,
|
||||
get_filename,
|
||||
get_ext,
|
||||
has_unwanted_extension,
|
||||
)
|
||||
from sabnzbd.constants import Status, GIGI, MAX_ASSEMBLER_QUEUE
|
||||
import sabnzbd.cfg as cfg
|
||||
from sabnzbd.nzbstuff import NzbObject, NzbFile
|
||||
@@ -334,29 +342,30 @@ def check_encrypted_and_unwanted_files(nzo: NzbObject, filepath: str) -> Tuple[b
|
||||
zf.setpassword(password)
|
||||
except rarfile.Error:
|
||||
# On weird passwords the setpassword() will fail
|
||||
# but the actual rartest() will work
|
||||
# but the actual testrar() will work
|
||||
pass
|
||||
try:
|
||||
zf.testrar()
|
||||
password_hit = password
|
||||
break
|
||||
except rarfile.RarWrongPassword:
|
||||
# This one really didn't work
|
||||
pass
|
||||
except rarfile.RarCRCError as e:
|
||||
# CRC errors can be thrown for wrong password or
|
||||
# missing the next volume (with correct password)
|
||||
if "cannot find volume" in str(e).lower():
|
||||
# We assume this one worked!
|
||||
password_hit = password
|
||||
break
|
||||
# This one didn't work
|
||||
pass
|
||||
except Exception as e:
|
||||
# Did we start from the right volume? Skip the checks for now.
|
||||
if match_str(
|
||||
str(e).lower(),
|
||||
("need to start extraction from a previous volume", "non-fatal error"),
|
||||
):
|
||||
return encrypted, unwanted
|
||||
# This one failed
|
||||
pass
|
||||
except:
|
||||
# All the other errors we skip, they might be fixable in post-proc.
|
||||
# For example starting from the wrong volume, or damaged files
|
||||
# This will cause the check to be performed again for the next rar, might
|
||||
# be disk-intensive! Could be removed later and just accept the password.
|
||||
return encrypted, unwanted
|
||||
|
||||
# Did any work?
|
||||
if password_hit:
|
||||
@@ -376,7 +385,7 @@ def check_encrypted_and_unwanted_files(nzo: NzbObject, filepath: str) -> Tuple[b
|
||||
if cfg.unwanted_extensions() and cfg.action_on_unwanted_extensions():
|
||||
for somefile in zf.namelist():
|
||||
logging.debug("File contains: %s", somefile)
|
||||
if get_ext(somefile).replace(".", "").lower() in cfg.unwanted_extensions():
|
||||
if has_unwanted_extension(somefile):
|
||||
logging.debug("Unwanted file %s", somefile)
|
||||
unwanted = somefile
|
||||
zf.close()
|
||||
|
||||
@@ -26,6 +26,7 @@ from typing import List, Dict, Optional
|
||||
|
||||
import sabnzbd
|
||||
from sabnzbd.constants import BYTES_FILE_NAME, KIBI
|
||||
from sabnzbd.misc import to_units
|
||||
import sabnzbd.cfg as cfg
|
||||
|
||||
DAY = float(24 * 60 * 60)
|
||||
@@ -100,6 +101,8 @@ class BPSMeter:
|
||||
self.bps_list: List[int] = []
|
||||
|
||||
self.server_bps: Dict[str, float] = {}
|
||||
self.cached_amount: Dict[str, int] = {}
|
||||
self.sum_cached_amount: int = 0
|
||||
self.day_total: Dict[str, int] = {}
|
||||
self.week_total: Dict[str, int] = {}
|
||||
self.month_total: Dict[str, int] = {}
|
||||
@@ -195,18 +198,24 @@ class BPSMeter:
|
||||
res = self.reset_quota()
|
||||
except:
|
||||
self.defaults()
|
||||
# Force update of counters and validate data
|
||||
try:
|
||||
for server in self.grand_total.keys():
|
||||
self.update(server)
|
||||
except TypeError:
|
||||
self.defaults()
|
||||
self.update()
|
||||
return res
|
||||
|
||||
def update(self, server: Optional[str] = None, amount: int = 0):
|
||||
def update(self, server: Optional[str] = None, amount: int = 0, force_full_update: bool = True):
|
||||
""" Update counters for "server" with "amount" bytes """
|
||||
t = time.time()
|
||||
|
||||
# Add amount to temporary storage
|
||||
if server:
|
||||
if server not in self.cached_amount:
|
||||
self.cached_amount[server] = 0
|
||||
self.server_bps[server] = 0.0
|
||||
self.cached_amount[server] += amount
|
||||
self.sum_cached_amount += amount
|
||||
|
||||
# Wait at least 0.05 seconds between each full update
|
||||
if not force_full_update and t - self.last_update < 0.05:
|
||||
return
|
||||
|
||||
if t > self.end_of_day:
|
||||
# current day passed. get new end of day
|
||||
self.day_label = time.strftime("%Y-%m-%d")
|
||||
@@ -221,60 +230,62 @@ class BPSMeter:
|
||||
self.month_total = {}
|
||||
self.end_of_month = next_month(t) - 1.0
|
||||
|
||||
if server:
|
||||
if server not in self.day_total:
|
||||
self.day_total[server] = 0
|
||||
self.day_total[server] += amount
|
||||
# Add amounts that have been stored temporarily to statistics
|
||||
for srv in self.cached_amount:
|
||||
cached_amount = self.cached_amount[srv]
|
||||
if cached_amount:
|
||||
self.cached_amount[srv] = 0
|
||||
if srv not in self.day_total:
|
||||
self.day_total[srv] = 0
|
||||
self.day_total[srv] += cached_amount
|
||||
|
||||
if server not in self.week_total:
|
||||
self.week_total[server] = 0
|
||||
self.week_total[server] += amount
|
||||
if srv not in self.week_total:
|
||||
self.week_total[srv] = 0
|
||||
self.week_total[srv] += cached_amount
|
||||
|
||||
if server not in self.month_total:
|
||||
self.month_total[server] = 0
|
||||
self.month_total[server] += amount
|
||||
if srv not in self.month_total:
|
||||
self.month_total[srv] = 0
|
||||
self.month_total[srv] += cached_amount
|
||||
|
||||
if server not in self.grand_total:
|
||||
self.grand_total[server] = 0
|
||||
self.grand_total[server] += amount
|
||||
if srv not in self.grand_total:
|
||||
self.grand_total[srv] = 0
|
||||
self.grand_total[srv] += cached_amount
|
||||
|
||||
if server not in self.timeline_total:
|
||||
self.timeline_total[server] = {}
|
||||
if self.day_label not in self.timeline_total[server]:
|
||||
self.timeline_total[server][self.day_label] = 0
|
||||
self.timeline_total[server][self.day_label] += amount
|
||||
if srv not in self.timeline_total:
|
||||
self.timeline_total[srv] = {}
|
||||
if self.day_label not in self.timeline_total[srv]:
|
||||
self.timeline_total[srv][self.day_label] = 0
|
||||
self.timeline_total[srv][self.day_label] += cached_amount
|
||||
|
||||
# Quota check
|
||||
if self.have_quota and self.quota_enabled:
|
||||
self.left -= amount
|
||||
if self.left <= 0.0:
|
||||
if not sabnzbd.Downloader.paused:
|
||||
sabnzbd.Downloader.pause()
|
||||
logging.warning(T("Quota spent, pausing downloading"))
|
||||
try:
|
||||
# Update server bps
|
||||
self.server_bps[srv] = (self.server_bps[srv] * (self.last_update - self.start_time) + cached_amount) / (
|
||||
t - self.start_time
|
||||
)
|
||||
except:
|
||||
self.server_bps[srv] = 0.0
|
||||
|
||||
# Quota check
|
||||
if self.have_quota and self.quota_enabled:
|
||||
self.left -= self.sum_cached_amount
|
||||
if self.left <= 0.0:
|
||||
if not sabnzbd.Downloader.paused:
|
||||
sabnzbd.Downloader.pause()
|
||||
logging.warning(T("Quota spent, pausing downloading"))
|
||||
|
||||
# Speedometer
|
||||
try:
|
||||
self.bps = (self.bps * (self.last_update - self.start_time) + amount) / (t - self.start_time)
|
||||
self.bps = (self.bps * (self.last_update - self.start_time) + self.sum_cached_amount) / (
|
||||
t - self.start_time
|
||||
)
|
||||
except:
|
||||
self.bps = 0.0
|
||||
self.server_bps = {}
|
||||
|
||||
if server and server not in self.server_bps:
|
||||
self.server_bps[server] = 0.0
|
||||
|
||||
for server_to_update in self.server_bps:
|
||||
try:
|
||||
# Only add data to the current server, update the rest to get correct average speed
|
||||
self.server_bps[server_to_update] = (
|
||||
self.server_bps[server_to_update] * (self.last_update - self.start_time)
|
||||
+ amount * (server_to_update == server)
|
||||
) / (t - self.start_time)
|
||||
except:
|
||||
self.server_bps[server_to_update] = 0.0
|
||||
|
||||
self.last_update = t
|
||||
|
||||
check_time = t - 5.0
|
||||
self.sum_cached_amount = 0
|
||||
|
||||
if self.start_time < check_time:
|
||||
self.start_time = check_time
|
||||
@@ -283,7 +294,7 @@ class BPSMeter:
|
||||
self.reset()
|
||||
|
||||
elif self.log_time < check_time:
|
||||
logging.debug("bps: %s", self.bps)
|
||||
logging.debug("Speed: %sB/s", to_units(self.bps))
|
||||
self.log_time = t
|
||||
|
||||
if self.speed_log_time < (t - 1.0):
|
||||
|
||||
@@ -133,7 +133,6 @@ https_chain = OptionDir("misc", "https_chain", create=False)
|
||||
enable_https = OptionBool("misc", "enable_https", False)
|
||||
# 0=local-only, 1=nzb, 2=api, 3=full_api, 4=webui, 5=webui with login for external
|
||||
inet_exposure = OptionNumber("misc", "inet_exposure", 0, protect=True)
|
||||
local_ranges = OptionList("misc", "local_ranges", protect=True)
|
||||
api_key = OptionStr("misc", "api_key", create_api_key())
|
||||
nzb_key = OptionStr("misc", "nzb_key", create_api_key())
|
||||
|
||||
@@ -196,6 +195,7 @@ sanitize_safe = OptionBool("misc", "sanitize_safe", False)
|
||||
cleanup_list = OptionList("misc", "cleanup_list")
|
||||
unwanted_extensions = OptionList("misc", "unwanted_extensions")
|
||||
action_on_unwanted_extensions = OptionNumber("misc", "action_on_unwanted_extensions", 0)
|
||||
unwanted_extensions_mode = OptionNumber("misc", "unwanted_extensions_mode", 0)
|
||||
new_nzb_on_failure = OptionBool("misc", "new_nzb_on_failure", False)
|
||||
history_retention = OptionStr("misc", "history_retention", "0")
|
||||
enable_meta = OptionBool("misc", "enable_meta", True)
|
||||
@@ -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)
|
||||
@@ -307,6 +307,7 @@ marker_file = OptionStr("misc", "nomedia_marker")
|
||||
ipv6_servers = OptionNumber("misc", "ipv6_servers", 1, 0, 2)
|
||||
url_base = OptionStr("misc", "url_base", "/sabnzbd", validation=validate_strip_right_slash)
|
||||
host_whitelist = OptionList("misc", "host_whitelist", validation=all_lowercase)
|
||||
local_ranges = OptionList("misc", "local_ranges", protect=True)
|
||||
max_url_retries = OptionNumber("misc", "max_url_retries", 10, 1)
|
||||
downloader_sleep_time = OptionNumber("misc", "downloader_sleep_time", 10, 0)
|
||||
ssdp_broadcast_interval = OptionNumber("misc", "ssdp_broadcast_interval", 15, 1, 600)
|
||||
|
||||
@@ -1131,13 +1131,13 @@ def validate_strip_right_slash(value):
|
||||
return None, value
|
||||
|
||||
|
||||
def validate_single_tag(value):
|
||||
def validate_single_tag(value: List[str]) -> Tuple[None, List[str]]:
|
||||
"""Don't split single indexer tags like "TV > HD"
|
||||
into ['TV', '>', 'HD']
|
||||
"""
|
||||
if len(value) == 3:
|
||||
if value[1] == ">":
|
||||
return None, " ".join(value)
|
||||
return None, [" ".join(value)]
|
||||
return None, value
|
||||
|
||||
|
||||
|
||||
@@ -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
|
||||
@@ -143,6 +141,8 @@ year_match = r"[\W]([1|2]\d{3})([^\w]|$)" # Something '(YYYY)' or '.YYYY.' or '
|
||||
|
||||
sample_match = r"((^|[\W_])(sample|proof))" # something-sample or something-proof
|
||||
|
||||
resolution_match = r"(^|[\W_])((240|360|480|540|576|720|900|1080|1440|2160|4320)[piP])([\W_]|$)" # 576i, 720p, 1080P
|
||||
|
||||
|
||||
class Status:
|
||||
COMPLETED = "Completed" # PP: Job is finished
|
||||
|
||||
@@ -46,7 +46,7 @@ except ImportError:
|
||||
|
||||
|
||||
class CrcError(Exception):
|
||||
def __init__(self, needcrc, gotcrc, data):
|
||||
def __init__(self, needcrc: int, gotcrc: int, data: bytes):
|
||||
super().__init__()
|
||||
self.needcrc = needcrc
|
||||
self.gotcrc = gotcrc
|
||||
@@ -154,13 +154,16 @@ class DecoderWorker(Thread):
|
||||
sabnzbd.NzbQueue.reset_try_lists(article)
|
||||
continue
|
||||
|
||||
except CrcError:
|
||||
except CrcError as crc_error:
|
||||
logging.info("CRC Error in %s" % art_id)
|
||||
|
||||
# Continue to the next one if we found new server
|
||||
if search_new_server(article):
|
||||
continue
|
||||
|
||||
# Store data, maybe par2 can still fix it
|
||||
decoded_data = crc_error.data
|
||||
|
||||
except (BadYenc, ValueError):
|
||||
# Handles precheck and badly formed articles
|
||||
if nzo.precheck and raw_data and raw_data[0].startswith(b"223 "):
|
||||
|
||||
@@ -89,6 +89,11 @@ def is_probably_obfuscated(myinputfilename):
|
||||
# exactly 32 hex digits, so:
|
||||
return True
|
||||
|
||||
# 0675e29e9abfd2.f7d069dab0b853283cc1b069a25f82.6547
|
||||
if re.findall(r"^[a-f0-9\.]{40,}$", filebasename):
|
||||
logging.debug("Obfuscated: starting with 40+ lower case hex digits and/or dots")
|
||||
return True
|
||||
|
||||
# /some/thing/abc.xyz.a4c567edbcbf27.BLA is certainly obfuscated
|
||||
if re.findall(r"^abc\.xyz", filebasename):
|
||||
logging.debug("Obfuscated: starts with 'abc.xyz'")
|
||||
@@ -127,14 +132,13 @@ def is_probably_obfuscated(myinputfilename):
|
||||
|
||||
|
||||
def deobfuscate_list(filelist, usefulname):
|
||||
""" Check all files in filelist, and if wanted, deobfuscate """
|
||||
""" Check all files in filelist, and if wanted, deobfuscate: rename to filename based on usefulname"""
|
||||
|
||||
# to be sure, only keep really exsiting files:
|
||||
filelist = [f for f in filelist if os.path.exists(f)]
|
||||
|
||||
# Search for par2 files in the filelist
|
||||
par2_files = [f for f in filelist if f.endswith(".par2")]
|
||||
|
||||
# Found any par2 files we can use?
|
||||
run_renamer = True
|
||||
if not par2_files:
|
||||
@@ -152,22 +156,57 @@ def deobfuscate_list(filelist, usefulname):
|
||||
|
||||
# No par2 files? Then we try to rename qualifying (big, not-excluded, obfuscated) files to the job-name
|
||||
if run_renamer:
|
||||
excluded_file_exts = EXCLUDED_FILE_EXTS
|
||||
# If there is a collection with bigger files with the same extension, we don't want to rename it
|
||||
extcounter = {}
|
||||
for file in filelist:
|
||||
if os.path.getsize(file) < MIN_FILE_SIZE:
|
||||
# too small to care
|
||||
continue
|
||||
_, ext = os.path.splitext(file)
|
||||
if ext in extcounter:
|
||||
extcounter[ext] += 1
|
||||
else:
|
||||
extcounter[ext] = 1
|
||||
if extcounter[ext] >= 3 and ext not in excluded_file_exts:
|
||||
# collection, and extension not yet in excluded_file_exts, so add it
|
||||
excluded_file_exts = (*excluded_file_exts, ext)
|
||||
logging.debug(
|
||||
"Found a collection of at least %s files with extension %s, so not renaming those files",
|
||||
extcounter[ext],
|
||||
ext,
|
||||
)
|
||||
|
||||
logging.debug("Trying to see if there are qualifying files to be deobfuscated")
|
||||
# We start with he biggest file ... probably the most important file
|
||||
filelist = sorted(filelist, key=os.path.getsize, reverse=True)
|
||||
for filename in filelist:
|
||||
# check that file is still there (and not renamed by the secondary renaming process below)
|
||||
if not os.path.isfile(filename):
|
||||
continue
|
||||
logging.debug("Deobfuscate inspecting %s", filename)
|
||||
file_size = os.path.getsize(filename)
|
||||
# Do we need to rename this file?
|
||||
# Criteria: big, not-excluded extension, obfuscated (in that order)
|
||||
if (
|
||||
file_size > MIN_FILE_SIZE
|
||||
and get_ext(filename) not in EXCLUDED_FILE_EXTS
|
||||
os.path.getsize(filename) > MIN_FILE_SIZE
|
||||
and get_ext(filename) not in excluded_file_exts
|
||||
and is_probably_obfuscated(filename) # this as last test to avoid unnecessary analysis
|
||||
):
|
||||
# OK, rename
|
||||
# Rename and make sure the new filename is unique
|
||||
path, file = os.path.split(filename)
|
||||
# construct new_name: <path><usefulname><extension>
|
||||
new_name = get_unique_filename("%s%s" % (os.path.join(path, usefulname), get_ext(filename)))
|
||||
logging.info("Deobfuscate renaming %s to %s", filename, new_name)
|
||||
# Rename and make sure the new filename is unique
|
||||
renamer(filename, new_name)
|
||||
# find other files with the same basename in filelist, and rename them in the same way:
|
||||
basedirfile, _ = os.path.splitext(filename) # something like "/home/this/myiso"
|
||||
for otherfile in filelist:
|
||||
if otherfile.startswith(basedirfile + ".") and os.path.isfile(otherfile):
|
||||
# yes, same basedirfile, only different extension
|
||||
remainingextension = otherfile.replace(basedirfile, "") # might be long ext, like ".dut.srt"
|
||||
new_name = get_unique_filename("%s%s" % (os.path.join(path, usefulname), remainingextension))
|
||||
logging.info("Deobfuscate renaming %s to %s", otherfile, new_name)
|
||||
# Rename and make sure the new filename is unique
|
||||
renamer(otherfile, new_name)
|
||||
else:
|
||||
logging.info("No qualifying files found to deobfuscate")
|
||||
|
||||
@@ -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:
|
||||
@@ -582,6 +582,9 @@ class Downloader(Thread):
|
||||
server.info = None
|
||||
self.force_disconnect = False
|
||||
|
||||
# Make sure we update the stats
|
||||
sabnzbd.BPSMeter.update()
|
||||
|
||||
# Exit-point
|
||||
if self.shutdown:
|
||||
logging.info("Shutting down")
|
||||
@@ -626,7 +629,7 @@ class Downloader(Thread):
|
||||
DOWNLOADER_CV.wait()
|
||||
|
||||
if not read:
|
||||
sabnzbd.BPSMeter.update()
|
||||
sabnzbd.BPSMeter.update(force_full_update=False)
|
||||
continue
|
||||
|
||||
for selected in read:
|
||||
@@ -640,7 +643,7 @@ class Downloader(Thread):
|
||||
bytes_received, done, skip = (0, False, False)
|
||||
|
||||
if skip:
|
||||
sabnzbd.BPSMeter.update()
|
||||
sabnzbd.BPSMeter.update(force_full_update=False)
|
||||
continue
|
||||
|
||||
if bytes_received < 1:
|
||||
@@ -654,13 +657,13 @@ class Downloader(Thread):
|
||||
# In case nzf has disappeared because the file was deleted before the update could happen
|
||||
pass
|
||||
|
||||
sabnzbd.BPSMeter.update(server.id, bytes_received, force_full_update=False)
|
||||
if self.bandwidth_limit:
|
||||
limit = self.bandwidth_limit
|
||||
if bytes_received + sabnzbd.BPSMeter.bps > limit:
|
||||
while sabnzbd.BPSMeter.bps > limit:
|
||||
if sabnzbd.BPSMeter.sum_cached_amount + sabnzbd.BPSMeter.bps > self.bandwidth_limit:
|
||||
sabnzbd.BPSMeter.update()
|
||||
while sabnzbd.BPSMeter.bps > self.bandwidth_limit:
|
||||
time.sleep(0.01)
|
||||
sabnzbd.BPSMeter.update()
|
||||
sabnzbd.BPSMeter.update(server.id, bytes_received)
|
||||
|
||||
if not done and nw.status_code != 222:
|
||||
if not nw.connected or nw.status_code == 480:
|
||||
|
||||
@@ -29,6 +29,7 @@ import time
|
||||
import fnmatch
|
||||
import stat
|
||||
import zipfile
|
||||
import ctypes
|
||||
from typing import Union, List, Tuple, Any, Dict, Optional
|
||||
|
||||
try:
|
||||
@@ -40,7 +41,7 @@ except ImportError:
|
||||
import sabnzbd
|
||||
from sabnzbd.decorators import synchronized
|
||||
from sabnzbd.constants import FUTURE_Q_FOLDER, JOB_ADMIN, GIGI, DEF_FILE_MAX
|
||||
from sabnzbd.encoding import correct_unknown_encoding
|
||||
from sabnzbd.encoding import correct_unknown_encoding, utob, ubtou
|
||||
from sabnzbd.utils import rarfile
|
||||
|
||||
# For Windows: determine executable extensions
|
||||
@@ -58,6 +59,23 @@ def get_ext(filename: str) -> str:
|
||||
return ""
|
||||
|
||||
|
||||
def has_unwanted_extension(filename: str) -> bool:
|
||||
""" Determine if a filename has an unwanted extension, given the configured mode """
|
||||
extension = get_ext(filename).replace(".", "")
|
||||
if extension and sabnzbd.cfg.unwanted_extensions():
|
||||
return (
|
||||
# Blacklisted
|
||||
sabnzbd.cfg.unwanted_extensions_mode() == 0
|
||||
and extension in sabnzbd.cfg.unwanted_extensions()
|
||||
) or (
|
||||
# Not whitelisted
|
||||
sabnzbd.cfg.unwanted_extensions_mode() == 1
|
||||
and extension not in sabnzbd.cfg.unwanted_extensions()
|
||||
)
|
||||
else:
|
||||
return bool(sabnzbd.cfg.unwanted_extensions_mode())
|
||||
|
||||
|
||||
def get_filename(path: str) -> str:
|
||||
""" Return path without the file extension """
|
||||
try:
|
||||
@@ -180,11 +198,11 @@ def sanitize_filename(name: str) -> str:
|
||||
# preserving the extension (max ext length 20)
|
||||
# Note: some filesystem can handle up to 255 UTF chars (which is more than 255 bytes) in the filename,
|
||||
# but we stay on the safe side: max DEF_FILE_MAX bytes
|
||||
if len(name.encode("utf8")) + len(ext.encode("utf8")) > DEF_FILE_MAX:
|
||||
if len(utob(name)) + len(utob(ext)) > DEF_FILE_MAX:
|
||||
logging.debug("Filename %s is too long, so truncating", name + ext)
|
||||
# Too long filenames are often caused by incorrect non-ascii chars,
|
||||
# so brute-force remove those non-ascii chars
|
||||
name = str(name.encode("ascii", "ignore"), "utf-8")
|
||||
name = ubtou(name.encode("ascii", "ignore"))
|
||||
# Now it's plain ASCII, so no need for len(str.encode()) anymore; plain len() is enough
|
||||
if len(name) + len(ext) > DEF_FILE_MAX:
|
||||
# still too long, limit the extension
|
||||
@@ -227,7 +245,6 @@ def sanitize_foldername(name: str) -> str:
|
||||
else:
|
||||
lst.append(ch)
|
||||
name = "".join(lst)
|
||||
name = name.strip()
|
||||
|
||||
if sabnzbd.WIN32 or sabnzbd.cfg.sanitize_safe():
|
||||
name = replace_win_devices(name)
|
||||
@@ -235,9 +252,14 @@ def sanitize_foldername(name: str) -> str:
|
||||
if len(name) >= sabnzbd.cfg.max_foldername_length():
|
||||
name = name[: sabnzbd.cfg.max_foldername_length()]
|
||||
|
||||
# And finally, make sure it doesn't end in a dot
|
||||
# And finally, make sure it doesn't end in a dot or a space
|
||||
# This is invalid on Windows and can cause trouble for some other tools
|
||||
if name != "." and name != "..":
|
||||
name = name.rstrip(".")
|
||||
# This would be perfect for := operator in Python 3.8+
|
||||
while len(name.strip().rstrip(".")) < len(name):
|
||||
name = name.strip().rstrip(".")
|
||||
|
||||
# Just to be sure we don't return nothing
|
||||
if not name:
|
||||
name = "unknown"
|
||||
|
||||
@@ -806,8 +828,9 @@ def get_filepath(path: str, nzo, filename: str):
|
||||
|
||||
|
||||
@synchronized(DIR_LOCK)
|
||||
def renamer(old: str, new: str):
|
||||
""" Rename file/folder with retries for Win32 """
|
||||
def renamer(old: str, new: str, create_local_directories: bool = False):
|
||||
"""Rename file/folder with retries for Win32
|
||||
Optionally alows the creation of local directories if they don't exist yet"""
|
||||
# Sanitize last part of new name
|
||||
path, name = os.path.split(new)
|
||||
new = os.path.join(path, sanitize_filename(name))
|
||||
@@ -816,6 +839,19 @@ def renamer(old: str, new: str):
|
||||
if old == new:
|
||||
return
|
||||
|
||||
# In case we want nonexistent directories to be created, check for directory escape (forbidden)
|
||||
if create_local_directories:
|
||||
oldpath, _ = os.path.split(old)
|
||||
# Check not outside directory
|
||||
# In case of "same_file() == 1": same directory, so nothing to do
|
||||
if same_file(oldpath, path) == 0:
|
||||
# Outside current directory, this is most likely malicious
|
||||
logging.error(T("Blocked attempt to create directory %s"), path)
|
||||
raise OSError("Refusing to go outside directory")
|
||||
elif same_file(oldpath, path) == 2:
|
||||
# Sub-directory, so create if does not yet exist:
|
||||
create_all_dirs(path)
|
||||
|
||||
logging.debug('Renaming "%s" to "%s"', old, new)
|
||||
if sabnzbd.WIN32:
|
||||
retries = 10
|
||||
@@ -913,6 +949,50 @@ def remove_all(path: str, pattern: str = "*", keep_folder: bool = False, recursi
|
||||
##############################################################################
|
||||
# Diskfree
|
||||
##############################################################################
|
||||
def disk_free_macos_clib_statfs64(directory: str) -> Tuple[int, int]:
|
||||
# MacOS only!
|
||||
# direct system call to c-lib's statfs(), not python's os.statvfs()
|
||||
# because statvfs() on MacOS has a rollover at 4TB (possibly a 32bit rollover with 10bit block size)
|
||||
# See https://bugs.python.org/issue43638
|
||||
# Based on code of pudquick and blackntan
|
||||
# Input: directory.
|
||||
# Output: disksize and available space, in bytes
|
||||
|
||||
# format & parameters: on MacOS, see "man statfs", lines starting at
|
||||
# "struct statfs { /* when _DARWIN_FEATURE_64_BIT_INODE is defined */"
|
||||
class statfs64(ctypes.Structure):
|
||||
_fields_ = [
|
||||
("f_bsize", ctypes.c_uint32),
|
||||
("f_iosize", ctypes.c_int32),
|
||||
("f_blocks", ctypes.c_uint64),
|
||||
("f_bfree", ctypes.c_uint64),
|
||||
("f_bavail", ctypes.c_uint64),
|
||||
("f_files", ctypes.c_uint64),
|
||||
("f_ffree", ctypes.c_uint64),
|
||||
("f_fsid", ctypes.c_uint64),
|
||||
("f_owner", ctypes.c_uint32),
|
||||
("f_type", ctypes.c_uint32),
|
||||
("f_flags", ctypes.c_uint32),
|
||||
("f_fssubtype", ctypes.c_uint32),
|
||||
("f_fstypename", ctypes.c_char * 16),
|
||||
("f_mntonname", ctypes.c_char * 1024),
|
||||
("f_mntfromname", ctypes.c_char * 1024),
|
||||
("f_reserved", ctypes.c_uint32 * 8),
|
||||
]
|
||||
|
||||
fs_info64 = statfs64() # set up the parameters to be filled out
|
||||
result = sabnzbd.MACOSLIBC.statfs64(
|
||||
ctypes.create_string_buffer(utob(directory)), ctypes.byref(fs_info64)
|
||||
) # fs_info64 gets filled out via the byref()
|
||||
if result == 0:
|
||||
# result = 0: "Upon successful completion, a value of 0 is returned."
|
||||
return fs_info64.f_blocks * fs_info64.f_bsize, fs_info64.f_bavail * fs_info64.f_bsize
|
||||
else:
|
||||
# result = -1: "Otherwise, -1 is returned and the global variable errno is set to indicate the error."
|
||||
logging.debug("Call to MACOSLIBC.statfs64 not successful. Value of errno is %s", ctypes.get_errno())
|
||||
return 0, 0
|
||||
|
||||
|
||||
def diskspace_base(dir_to_check: str) -> Tuple[float, float]:
|
||||
""" Return amount of free and used diskspace in GBytes """
|
||||
# Find first folder level that exists in the path
|
||||
@@ -927,6 +1007,10 @@ def diskspace_base(dir_to_check: str) -> Tuple[float, float]:
|
||||
return disk_size / GIGI, available / GIGI
|
||||
except:
|
||||
return 0.0, 0.0
|
||||
elif sabnzbd.DARWIN:
|
||||
# MacOS diskfree ... via c-lib call statfs()
|
||||
disk_size, available = disk_free_macos_clib_statfs64(dir_to_check)
|
||||
return disk_size / GIGI, available / GIGI
|
||||
elif hasattr(os, "statvfs"):
|
||||
# posix diskfree
|
||||
try:
|
||||
|
||||
@@ -30,10 +30,12 @@ import hashlib
|
||||
import socket
|
||||
import ssl
|
||||
import functools
|
||||
import ipaddress
|
||||
from threading import Thread
|
||||
from random import randint
|
||||
from xml.sax.saxutils import escape
|
||||
from Cheetah.Template import Template
|
||||
from typing import Optional, Callable, Union
|
||||
|
||||
import sabnzbd
|
||||
import sabnzbd.rss
|
||||
@@ -44,10 +46,12 @@ 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,
|
||||
is_loopback_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
|
||||
@@ -80,16 +84,60 @@ from sabnzbd.api import (
|
||||
##############################################################################
|
||||
# Security functions
|
||||
##############################################################################
|
||||
def secured_expose(wrap_func=None, check_configlock=False, check_api_key=False):
|
||||
_MSG_ACCESS_DENIED = "Access denied"
|
||||
_MSG_ACCESS_DENIED_CONFIG_LOCK = "Access denied - Configuration locked"
|
||||
_MSG_ACCESS_DENIED_HOSTNAME = "Access denied - Hostname verification failed: https://sabnzbd.org/hostname-check"
|
||||
_MSG_MISSING_AUTH = "Missing authentication"
|
||||
_MSG_APIKEY_REQUIRED = "API Key Required"
|
||||
_MSG_APIKEY_INCORRECT = "API Key Incorrect"
|
||||
|
||||
|
||||
def secured_expose(
|
||||
wrap_func: Optional[Callable] = None,
|
||||
check_configlock: bool = False,
|
||||
check_for_login: bool = True,
|
||||
check_api_key: bool = False,
|
||||
access_type: int = 4,
|
||||
) -> Union[Callable, str]:
|
||||
""" Wrapper for both cherrypy.expose and login/access check """
|
||||
if not wrap_func:
|
||||
return functools.partial(secured_expose, check_configlock=check_configlock, check_api_key=check_api_key)
|
||||
return functools.partial(
|
||||
secured_expose,
|
||||
check_configlock=check_configlock,
|
||||
check_for_login=check_for_login,
|
||||
check_api_key=check_api_key,
|
||||
access_type=access_type,
|
||||
)
|
||||
|
||||
# Expose to cherrypy
|
||||
wrap_func.exposed = True
|
||||
|
||||
@functools.wraps(wrap_func)
|
||||
def internal_wrap(*args, **kwargs):
|
||||
# Label for logging in this and other functions, handling X-Forwarded-For
|
||||
# The cherrypy.request object allows adding custom attributes
|
||||
if cherrypy.request.headers.get("X-Forwarded-For"):
|
||||
cherrypy.request.remote_label = "%s (X-Forwarded-For: %s) [%s]" % (
|
||||
cherrypy.request.remote.ip,
|
||||
cherrypy.request.headers.get("X-Forwarded-For"),
|
||||
cherrypy.request.headers.get("User-Agent"),
|
||||
)
|
||||
else:
|
||||
cherrypy.request.remote_label = "%s [%s]" % (
|
||||
cherrypy.request.remote.ip,
|
||||
cherrypy.request.headers.get("User-Agent"),
|
||||
)
|
||||
|
||||
# Log all requests
|
||||
if cfg.api_logging():
|
||||
logging.debug(
|
||||
"Request %s %s from %s %s",
|
||||
cherrypy.request.method,
|
||||
cherrypy.request.path_info,
|
||||
cherrypy.request.remote_label,
|
||||
kwargs,
|
||||
)
|
||||
|
||||
# Add X-Frame-Headers headers to page-requests
|
||||
if cfg.x_frame_options():
|
||||
cherrypy.response.headers["X-Frame-Options"] = "SameOrigin"
|
||||
@@ -97,26 +145,27 @@ def secured_expose(wrap_func=None, check_configlock=False, check_api_key=False):
|
||||
# Check if config is locked
|
||||
if check_configlock and cfg.configlock():
|
||||
cherrypy.response.status = 403
|
||||
return "Access denied - Configuration locked"
|
||||
return _MSG_ACCESS_DENIED_CONFIG_LOCK
|
||||
|
||||
# Check if external access
|
||||
if not check_access():
|
||||
# Check if external access and if it's allowed
|
||||
if not check_access(access_type=access_type, warn_user=True):
|
||||
cherrypy.response.status = 403
|
||||
return "Access denied"
|
||||
return _MSG_ACCESS_DENIED
|
||||
|
||||
# Verify login status, only for non-key pages
|
||||
if not check_login() and not check_api_key:
|
||||
if check_for_login and not check_api_key and not check_login():
|
||||
raise Raiser("/login/")
|
||||
|
||||
# Verify host used for the visit
|
||||
if not check_hostname():
|
||||
cherrypy.response.status = 403
|
||||
return "Access denied - Hostname verification failed: https://sabnzbd.org/hostname-check"
|
||||
return _MSG_ACCESS_DENIED_HOSTNAME
|
||||
|
||||
# Some pages need correct API key
|
||||
if check_api_key:
|
||||
msg = check_apikey(kwargs)
|
||||
if msg:
|
||||
cherrypy.response.status = 403
|
||||
return msg
|
||||
|
||||
# All good, cool!
|
||||
@@ -125,7 +174,7 @@ def secured_expose(wrap_func=None, check_configlock=False, check_api_key=False):
|
||||
return internal_wrap
|
||||
|
||||
|
||||
def check_access(access_type=4):
|
||||
def check_access(access_type: int = 4, warn_user: bool = False) -> bool:
|
||||
"""Check if external address is allowed given access_type:
|
||||
1=nzb
|
||||
2=api
|
||||
@@ -133,17 +182,36 @@ def check_access(access_type=4):
|
||||
4=webui
|
||||
5=webui with login for external
|
||||
"""
|
||||
referrer = cherrypy.request.remote.ip
|
||||
# Easy, it's allowed
|
||||
if access_type <= cfg.inet_exposure():
|
||||
return True
|
||||
|
||||
# CherryPy will report ::ffff:192.168.0.10 on dual-stack situation
|
||||
# It will always contain that ::ffff: prefix
|
||||
range_ok = not cfg.local_ranges() or bool(
|
||||
[1 for r in cfg.local_ranges() if (referrer.startswith(r) or referrer.replace("::ffff:", "").startswith(r))]
|
||||
)
|
||||
allowed = referrer in ("127.0.0.1", "::ffff:127.0.0.1", "::1") or range_ok or access_type <= cfg.inet_exposure()
|
||||
if not allowed:
|
||||
logging.debug("Refused connection from %s", referrer)
|
||||
return allowed
|
||||
# It will always contain that ::ffff: prefix, the ipaddress module can handle that
|
||||
remote_ip = cherrypy.request.remote.ip
|
||||
|
||||
# Check for localhost
|
||||
if is_loopback_addr(remote_ip):
|
||||
return True
|
||||
|
||||
# No special ranged defined
|
||||
is_allowed = False
|
||||
if not cfg.local_ranges():
|
||||
try:
|
||||
is_allowed = ipaddress.ip_address(remote_ip).is_private
|
||||
except ValueError:
|
||||
# Something malformed, reject
|
||||
pass
|
||||
else:
|
||||
# Get rid off the special dual-stack notation
|
||||
if remote_ip.startswith("::ffff:") and not remote_ip.find(".") < 0:
|
||||
remote_ip = remote_ip.replace("::ffff:", "")
|
||||
is_allowed = any(remote_ip.startswith(r) for r in cfg.local_ranges())
|
||||
|
||||
# Reject
|
||||
if not is_allowed and warn_user:
|
||||
log_warning_and_ip(T("Refused connection from:"))
|
||||
return is_allowed
|
||||
|
||||
|
||||
def check_hostname():
|
||||
@@ -165,7 +233,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
|
||||
@@ -269,31 +337,30 @@ def check_apikey(kwargs):
|
||||
mode = kwargs.get("mode", "")
|
||||
name = kwargs.get("name", "")
|
||||
|
||||
# Lookup required access level, returns 4 for config-things
|
||||
# Lookup required access level for the specific api-call
|
||||
req_access = sabnzbd.api.api_level(mode, name)
|
||||
if not check_access(req_access, warn_user=True):
|
||||
return _MSG_ACCESS_DENIED
|
||||
|
||||
if req_access == 1 and check_access(1):
|
||||
# NZB-only actions
|
||||
pass
|
||||
elif not check_access(req_access):
|
||||
return "Access denied"
|
||||
# Skip for auth and version calls
|
||||
if mode in ("version", "auth"):
|
||||
return None
|
||||
|
||||
# First check API-key, if OK that's sufficient
|
||||
if not cfg.disable_key():
|
||||
key = kwargs.get("apikey")
|
||||
if not key:
|
||||
if cfg.api_warnings():
|
||||
log_warning_and_ip(
|
||||
T("API Key missing, please enter the api key from Config->General into your 3rd party program:")
|
||||
)
|
||||
return "API Key Required"
|
||||
log_warning_and_ip(
|
||||
T("API Key missing, please enter the api key from Config->General into your 3rd party program:")
|
||||
)
|
||||
return _MSG_APIKEY_REQUIRED
|
||||
elif req_access == 1 and key == cfg.nzb_key():
|
||||
return None
|
||||
elif key == cfg.api_key():
|
||||
return None
|
||||
else:
|
||||
log_warning_and_ip(T("API Key incorrect, Use the api key from Config->General in your 3rd party program:"))
|
||||
return "API Key Incorrect"
|
||||
return _MSG_APIKEY_INCORRECT
|
||||
|
||||
# No active API-key, check web credentials instead
|
||||
if cfg.username() and cfg.password():
|
||||
@@ -302,47 +369,37 @@ def check_apikey(kwargs):
|
||||
):
|
||||
pass
|
||||
else:
|
||||
if cfg.api_warnings():
|
||||
log_warning_and_ip(
|
||||
T(
|
||||
"Authentication missing, please enter username/password from Config->General into your 3rd party program:"
|
||||
)
|
||||
log_warning_and_ip(
|
||||
T(
|
||||
"Authentication missing, please enter username/password from Config->General into your 3rd party program:"
|
||||
)
|
||||
return "Missing authentication"
|
||||
)
|
||||
return _MSG_MISSING_AUTH
|
||||
return None
|
||||
|
||||
|
||||
def log_warning_and_ip(txt):
|
||||
""" Include the IP and the Proxy-IP for warnings """
|
||||
# Was it proxy forwarded?
|
||||
xff = cherrypy.request.headers.get("X-Forwarded-For")
|
||||
if xff:
|
||||
txt = "%s %s (X-Forwarded-For: %s)>%s" % (
|
||||
txt,
|
||||
cherrypy.request.remote.ip,
|
||||
xff,
|
||||
cherrypy.request.headers.get("User-Agent", "??"),
|
||||
)
|
||||
else:
|
||||
txt = "%s %s>%s" % (txt, cherrypy.request.remote.ip, cherrypy.request.headers.get("User-Agent", "??"))
|
||||
logging.warning(txt)
|
||||
if cfg.api_warnings():
|
||||
logging.warning("%s %s", txt, cherrypy.request.remote_label)
|
||||
|
||||
|
||||
##############################################################################
|
||||
# Helper raiser functions
|
||||
##############################################################################
|
||||
def Raiser(root="", **kwargs):
|
||||
args = {}
|
||||
for key in kwargs:
|
||||
val = kwargs.get(key)
|
||||
if val:
|
||||
args[key] = val
|
||||
def Raiser(root: str = "", **kwargs):
|
||||
# Add extras
|
||||
if args:
|
||||
root = "%s?%s" % (root, urllib.parse.urlencode(args))
|
||||
if kwargs:
|
||||
root = "%s?%s" % (root, urllib.parse.urlencode(kwargs))
|
||||
|
||||
# Optionally add the leading /sabnzbd/ (or what the user set)
|
||||
if not root.startswith(cfg.url_base()):
|
||||
root = cherrypy.request.script_name + root
|
||||
|
||||
# Log the redirect
|
||||
if cfg.api_logging():
|
||||
logging.debug("Request %s %s redirected to %s", cherrypy.request.method, cherrypy.request.path_info, root)
|
||||
|
||||
# Send the redirect
|
||||
return cherrypy.HTTPRedirect(root)
|
||||
|
||||
@@ -428,9 +485,9 @@ class MainPage:
|
||||
sabnzbd.unpause_all()
|
||||
raise Raiser(self.__root)
|
||||
|
||||
@cherrypy.expose
|
||||
@secured_expose(check_api_key=True, access_type=1)
|
||||
def api(self, **kwargs):
|
||||
""" Redirect to API-handler """
|
||||
""" Redirect to API-handler, we check the access_type in the API-handler """
|
||||
return api_handler(kwargs)
|
||||
|
||||
@secured_expose
|
||||
@@ -472,13 +529,11 @@ class MainPage:
|
||||
@secured_expose
|
||||
def description_xml(self, **kwargs):
|
||||
""" Provide the description.xml which was broadcast via SSDP """
|
||||
logging.debug(
|
||||
"description.xml was requested from %s by %s",
|
||||
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 +564,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
|
||||
@@ -630,7 +685,7 @@ def get_access_info():
|
||||
|
||||
##############################################################################
|
||||
class LoginPage:
|
||||
@cherrypy.expose
|
||||
@secured_expose(check_for_login=False)
|
||||
def index(self, **kwargs):
|
||||
# Base output var
|
||||
info = build_header(sabnzbd.WEB_DIR_CONFIG)
|
||||
@@ -645,27 +700,18 @@ class LoginPage:
|
||||
if check_login():
|
||||
raise Raiser(cherrypy.request.script_name + "/")
|
||||
|
||||
# Was it proxy forwarded?
|
||||
xff = cherrypy.request.headers.get("X-Forwarded-For")
|
||||
|
||||
# Check login info
|
||||
if kwargs.get("username") == cfg.username() and kwargs.get("password") == cfg.password():
|
||||
# Save login cookie
|
||||
set_login_cookie(remember_me=kwargs.get("remember_me", False))
|
||||
# Log the succes
|
||||
if xff:
|
||||
logging.info("Successful login from %s (X-Forwarded-For: %s)", cherrypy.request.remote.ip, xff)
|
||||
else:
|
||||
logging.info("Successful login from %s", cherrypy.request.remote.ip)
|
||||
# Log the success
|
||||
logging.info("Successful login from %s", cherrypy.request.remote_label)
|
||||
# Redirect
|
||||
raise Raiser(cherrypy.request.script_name + "/")
|
||||
elif kwargs.get("username") or kwargs.get("password"):
|
||||
info["error"] = T("Authentication failed, check username/password.")
|
||||
# Warn about the potential security problem
|
||||
fail_msg = T("Unsuccessful login attempt from %s") % cherrypy.request.remote.ip
|
||||
if xff:
|
||||
fail_msg = "%s (X-Forwarded-For: %s)" % (fail_msg, xff)
|
||||
logging.warning(fail_msg)
|
||||
logging.warning(T("Unsuccessful login attempt from %s"), cherrypy.request.remote_label)
|
||||
|
||||
# Show login
|
||||
template = Template(
|
||||
@@ -1227,6 +1273,7 @@ SWITCH_LIST = (
|
||||
"new_nzb_on_failure",
|
||||
"unwanted_extensions",
|
||||
"action_on_unwanted_extensions",
|
||||
"unwanted_extensions_mode",
|
||||
"sanitize_safe",
|
||||
"rating_enable",
|
||||
"rating_api_key",
|
||||
@@ -1327,7 +1374,7 @@ SPECIAL_BOOL_LIST = (
|
||||
"html_login",
|
||||
"wait_for_dfolder",
|
||||
"max_art_opt",
|
||||
"enable_bonjour",
|
||||
"enable_broadcast",
|
||||
"warn_dupl_jobs",
|
||||
"replace_illegal",
|
||||
"backup_for_duplicates",
|
||||
@@ -1347,13 +1394,19 @@ SPECIAL_VALUE_LIST = (
|
||||
"max_foldername_length",
|
||||
"show_sysload",
|
||||
"url_base",
|
||||
"num_decoders",
|
||||
"direct_unpack_threads",
|
||||
"ipv6_servers",
|
||||
"selftest_host",
|
||||
"rating_host",
|
||||
"ssdp_broadcast_interval",
|
||||
)
|
||||
SPECIAL_LIST_LIST = ("rss_odd_titles", "quick_check_ext_ignore", "host_whitelist")
|
||||
SPECIAL_LIST_LIST = (
|
||||
"rss_odd_titles",
|
||||
"quick_check_ext_ignore",
|
||||
"host_whitelist",
|
||||
"local_ranges",
|
||||
)
|
||||
|
||||
|
||||
class ConfigSpecial:
|
||||
@@ -1404,7 +1457,6 @@ GENERAL_LIST = (
|
||||
"refresh_rate",
|
||||
"language",
|
||||
"cache_limit",
|
||||
"local_ranges",
|
||||
"inet_exposure",
|
||||
"enable_https",
|
||||
"https_port",
|
||||
@@ -1482,7 +1534,6 @@ class ConfigGeneral:
|
||||
conf["bandwidth_max"] = cfg.bandwidth_max()
|
||||
conf["bandwidth_perc"] = cfg.bandwidth_perc()
|
||||
conf["nzb_key"] = cfg.nzb_key()
|
||||
conf["local_ranges"] = cfg.local_ranges.get_string()
|
||||
conf["my_lcldata"] = cfg.admin_dir.get_clipped_path()
|
||||
conf["caller_url"] = cherrypy.request.base + cfg.url_base()
|
||||
|
||||
|
||||
191
sabnzbd/lang.py
191
sabnzbd/lang.py
@@ -38,7 +38,7 @@ import glob
|
||||
import os
|
||||
import locale
|
||||
|
||||
__all__ = ["set_locale_info", "set_language", "list_languages"]
|
||||
__all__ = ["set_locale_info", "set_language", "list_languages", "is_rtl"]
|
||||
|
||||
_DOMAIN = "" # Holds translation domain
|
||||
_LOCALEDIR = "" # Holds path to the translation base folder
|
||||
@@ -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
|
||||
|
||||
@@ -781,11 +781,7 @@ def get_all_passwords(nzo):
|
||||
meta_passwords.append(pw)
|
||||
|
||||
if meta_passwords:
|
||||
if nzo.password == meta_passwords[0]:
|
||||
# this nzo.password came from meta, so don't use it twice
|
||||
passwords.extend(meta_passwords[1:])
|
||||
else:
|
||||
passwords.extend(meta_passwords)
|
||||
passwords.extend(meta_passwords)
|
||||
logging.info("Read %s passwords from meta data in NZB: %s", len(meta_passwords), meta_passwords)
|
||||
|
||||
pw_file = cfg.password_file.get_path()
|
||||
@@ -808,6 +804,7 @@ def get_all_passwords(nzo):
|
||||
)
|
||||
except:
|
||||
logging.warning(T("Failed to read the password file %s"), pw_file)
|
||||
logging.info("Traceback: ", exc_info=True)
|
||||
|
||||
if nzo.password:
|
||||
# If an explicit password was set, add a retry without password, just in case.
|
||||
@@ -816,7 +813,7 @@ def get_all_passwords(nzo):
|
||||
# If we're not sure about encryption, start with empty password
|
||||
# and make sure we have at least the empty password
|
||||
passwords.insert(0, "")
|
||||
return passwords
|
||||
return set(passwords)
|
||||
|
||||
|
||||
def find_on_path(targets):
|
||||
@@ -837,27 +834,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]:
|
||||
@@ -994,7 +1011,7 @@ def build_and_run_command(command: List[str], flatten_command=False, **kwargs):
|
||||
raise IOError
|
||||
elif script_file.read(2) != "#!":
|
||||
# No shebang (#!) defined, add default python
|
||||
command.insert(0, "python")
|
||||
command.insert(0, sys.executable if sys.executable else "python")
|
||||
|
||||
if sabnzbd.newsunpack.IONICE_COMMAND and cfg.ionice():
|
||||
ionice = cfg.ionice().split()
|
||||
|
||||
@@ -2077,7 +2077,14 @@ def quick_check_set(set, nzo):
|
||||
if nzf.md5sum == md5pack[file]:
|
||||
try:
|
||||
logging.debug("Quick-check will rename %s to %s", nzf.filename, file)
|
||||
renamer(os.path.join(nzo.download_path, nzf.filename), os.path.join(nzo.download_path, file))
|
||||
|
||||
# Note: file can and is allowed to be in a subdirectory.
|
||||
# Subdirectories in par2 always contain "/", not "\"
|
||||
renamer(
|
||||
os.path.join(nzo.download_path, nzf.filename),
|
||||
os.path.join(nzo.download_path, file),
|
||||
create_local_directories=True,
|
||||
)
|
||||
renames[file] = nzf.filename
|
||||
nzf.filename = file
|
||||
result &= True
|
||||
@@ -2348,14 +2355,25 @@ def pre_queue(nzo: NzbObject, pp, cat):
|
||||
|
||||
output = platform_btou(p.stdout.read())
|
||||
ret = p.wait()
|
||||
logging.info("Pre-queue script returns %s and output=\n%s", ret, output)
|
||||
logging.info("Pre-queue script returned %s and output=\n%s", ret, output)
|
||||
if ret == 0:
|
||||
n = 0
|
||||
for line in output.split("\n"):
|
||||
line = line.strip("\r\n '\"")
|
||||
if n < len(values) and line:
|
||||
values[n] = line
|
||||
n += 1
|
||||
split_output = output.splitlines()
|
||||
try:
|
||||
# Extract category line from pre-queue output
|
||||
pre_queue_category = split_output[3].strip(" '\"")
|
||||
except IndexError:
|
||||
pre_queue_category = None
|
||||
|
||||
for index, line in enumerate(split_output):
|
||||
line = line.strip(" '\"")
|
||||
if index < len(values):
|
||||
if line:
|
||||
values[index] = line
|
||||
elif pre_queue_category and index in (2, 4, 5):
|
||||
# Preserve empty pp, script, and priority lines to prevent
|
||||
# pre-existing values from overriding category-based settings
|
||||
values[index] = ""
|
||||
|
||||
accept = int_conv(values[0])
|
||||
if accept < 1:
|
||||
logging.info("Pre-Q refuses %s", nzo.final_name)
|
||||
|
||||
@@ -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?
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user