mirror of
https://github.com/sabnzbd/sabnzbd.git
synced 2026-01-06 06:28:45 -05:00
Compare commits
129 Commits
2.0.0Beta1
...
1.0.2
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
b7e2bd9684 | ||
|
|
f0a243e3d3 | ||
|
|
6e108c9ef2 | ||
|
|
89edcc1924 | ||
|
|
8a6aca47a1 | ||
|
|
d03e5780b8 | ||
|
|
209d8f9b40 | ||
|
|
c257b1be3d | ||
|
|
2c48c8de2e | ||
|
|
a767ef6aed | ||
|
|
ad61d1dd03 | ||
|
|
33c3d187a0 | ||
|
|
4eb486d4e2 | ||
|
|
bfb6c167a4 | ||
|
|
44abf3bdf6 | ||
|
|
c950572592 | ||
|
|
3999cb13fd | ||
|
|
af65075f0c | ||
|
|
de2a2b465b | ||
|
|
cd7a77f02d | ||
|
|
f4a5394b63 | ||
|
|
3fb6a8dedb | ||
|
|
50c8f84eba | ||
|
|
2c7ecdee92 | ||
|
|
72390a793a | ||
|
|
04ad4e5d3e | ||
|
|
5ef9c6a433 | ||
|
|
e6baffc839 | ||
|
|
e361eb25a5 | ||
|
|
9b420e91c9 | ||
|
|
3a4bf971b2 | ||
|
|
1128691c5d | ||
|
|
15043aef3f | ||
|
|
2a3b4afa03 | ||
|
|
00a98efa81 | ||
|
|
f013dd7f0d | ||
|
|
7b91b1c769 | ||
|
|
5583cce322 | ||
|
|
b995c5f992 | ||
|
|
214ac4a53d | ||
|
|
c0f2f59fc1 | ||
|
|
b90a847a6f | ||
|
|
a58bb385f5 | ||
|
|
9754baeb1c | ||
|
|
ffcd154966 | ||
|
|
97cfe9488c | ||
|
|
374b6f616a | ||
|
|
e2f51595b6 | ||
|
|
04091a16aa | ||
|
|
9d9d2fd9a2 | ||
|
|
5746115331 | ||
|
|
42f1a4926c | ||
|
|
7d87fd461b | ||
|
|
1ba9976979 | ||
|
|
659c199043 | ||
|
|
81a3f53226 | ||
|
|
1cbff28f67 | ||
|
|
8e15acbf30 | ||
|
|
e07be60db6 | ||
|
|
539c9662ff | ||
|
|
b396014f8d | ||
|
|
1db32415b6 | ||
|
|
b24629db6b | ||
|
|
9b5cdcf8fb | ||
|
|
4831415d14 | ||
|
|
a4c51f0b20 | ||
|
|
ec3ba1fb93 | ||
|
|
61966f7036 | ||
|
|
4f69e81841 | ||
|
|
d0d90581df | ||
|
|
8ea5c27633 | ||
|
|
517500fdf3 | ||
|
|
c4c1c9b6ab | ||
|
|
2388889ede | ||
|
|
55cfe878d7 | ||
|
|
a2daaee468 | ||
|
|
2c360e395e | ||
|
|
399cfee594 | ||
|
|
be646ae6ab | ||
|
|
b470253d9f | ||
|
|
b83c493492 | ||
|
|
991277bb01 | ||
|
|
5626013b81 | ||
|
|
2810d37758 | ||
|
|
c2f08f01e0 | ||
|
|
17ff087e06 | ||
|
|
77de565b7c | ||
|
|
54d238aa4d | ||
|
|
379d09f8cc | ||
|
|
00de72b127 | ||
|
|
f9c84fa7dd | ||
|
|
c8e46691bb | ||
|
|
df1bb636e5 | ||
|
|
ff886fad0d | ||
|
|
6dbee7a413 | ||
|
|
3f8fcd7172 | ||
|
|
d94f7388e6 | ||
|
|
ad8b49fea8 | ||
|
|
ce00270c12 | ||
|
|
8c501f8f58 | ||
|
|
ce313ebc65 | ||
|
|
887ad881a2 | ||
|
|
ce40827552 | ||
|
|
2777d89482 | ||
|
|
727b300a0e | ||
|
|
652b021a8e | ||
|
|
fdf33acfbb | ||
|
|
b001bc9b6f | ||
|
|
8802cb1d8c | ||
|
|
e19a2fbae7 | ||
|
|
53e38f98f9 | ||
|
|
e783e227f6 | ||
|
|
f3dfbe4181 | ||
|
|
bcd8ca8bc4 | ||
|
|
816d6a63cd | ||
|
|
88d3f25700 | ||
|
|
80f69b11db | ||
|
|
81a11f20c8 | ||
|
|
9e2a839953 | ||
|
|
3cefcde270 | ||
|
|
87a1eacfe7 | ||
|
|
7cbc1a8419 | ||
|
|
7b5570eb0b | ||
|
|
1a43a4dcf0 | ||
|
|
2c2a6592c7 | ||
|
|
f31de6ee4e | ||
|
|
8fcd1f6b6c | ||
|
|
d7f3a473d7 | ||
|
|
ab2eb0c94e |
@@ -1,5 +1,5 @@
|
||||
*******************************************
|
||||
*** This is SABnzbd 0.8.0 ***
|
||||
*** This is SABnzbd 1.0.2 ***
|
||||
*******************************************
|
||||
SABnzbd is an open-source cross-platform binary newsreader.
|
||||
It simplifies the process of downloading from Usenet dramatically,
|
||||
@@ -12,8 +12,8 @@ and offers a complete API for third-party applications to hook into.
|
||||
There is an extensive Wiki on the use of SABnzbd.
|
||||
http://wiki.sabnzbd.org/
|
||||
|
||||
IMPORTANT INFORMATION about release 0.8.0:
|
||||
http://wiki.sabnzbd.org/introducing-0-8-0
|
||||
IMPORTANT INFORMATION about release 1.0.0:
|
||||
http://wiki.sabnzbd.org/introducing-1-0-0
|
||||
|
||||
|
||||
Please also read the file "ISSUES.txt"
|
||||
@@ -37,6 +37,6 @@ Install new version
|
||||
Start SABnzbd.
|
||||
|
||||
The organization of the download queue is different from 0.7.x (and older).
|
||||
0.8.0 will not finish downloading an existing queue.
|
||||
1.0.0 will not finish downloading an existing queue.
|
||||
Also, your sabnzbd.ini file will be upgraded, making it
|
||||
incompatible with older releases.
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
SABnzbd 0.8.0
|
||||
SABnzbd 1.0.2
|
||||
|
||||
-------------------------------------------------------------------------------
|
||||
0) LICENSE
|
||||
|
||||
@@ -24,13 +24,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: http://wiki.sabnzbd.org/configure-special-0-8
|
||||
See: http://wiki.sabnzbd.org/configure-special-1-0
|
||||
|
||||
- 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: http://wiki.sabnzbd.org/configure-special-0-8
|
||||
See: http://wiki.sabnzbd.org/configure-special-1-0
|
||||
|
||||
- On OSX you may encounter downloaded files with foreign characters.
|
||||
The par2 repair may fail when the files were created on a Windows system.
|
||||
@@ -41,7 +41,7 @@
|
||||
You will see this only when downloaded files contain accented characters.
|
||||
You need to fix it yourself by running the convmv utility (available for most Linux platforms).
|
||||
Possible the file system override setting 'fsys_type' might be solve things:
|
||||
See: http://wiki.sabnzbd.org/configure-special-0-8
|
||||
See: http://wiki.sabnzbd.org/configure-special-1-0
|
||||
|
||||
- The "Watched Folder" sometimes fails to delete the NZB files it has
|
||||
processed. This happens when other software still accesses these files.
|
||||
@@ -81,4 +81,4 @@
|
||||
- Squeeze Linux
|
||||
There is a "special" option that will allow you to select an alternative library.
|
||||
use_pickle = 1
|
||||
See: http://wiki.sabnzbd.org/configure-special-0-8
|
||||
See: http://wiki.sabnzbd.org/configure-special-1-0
|
||||
|
||||
4
PKG-INFO
4
PKG-INFO
@@ -1,7 +1,7 @@
|
||||
Metadata-Version: 1.0
|
||||
Name: SABnzbd
|
||||
Version: 0.8.0Beta4
|
||||
Summary: SABnzbd-0.8.0Beta4
|
||||
Version: 1.0.2
|
||||
Summary: SABnzbd-1.0.2
|
||||
Home-page: http://sabnzbd.org
|
||||
Author: The SABnzbd Team
|
||||
Author-email: team@sabnzbd.org
|
||||
|
||||
101
README.mkd
101
README.mkd
@@ -1,71 +1,53 @@
|
||||
Release Notes - SABnzbd 0.8.0Beta4
|
||||
====================================
|
||||
Release Notes - SABnzbd 1.0.2
|
||||
===============================
|
||||
|
||||
## Changes in Beta4
|
||||
- Unicode crashes in user interface fixed
|
||||
- Glitter skin improved
|
||||
- Resume can now give notification
|
||||
- In Config->Server, show active servers before inactive ones
|
||||
- Update unrar to 5.30
|
||||
- Added Windows Notifications (local)
|
||||
- Updated many localizations
|
||||
|
||||
## Changes in Beta3
|
||||
- Speedlimit corrections
|
||||
- Windows build now verifies https certificates
|
||||
- Windows build now supports TLS 1.2
|
||||
- Fixed bug that could lead to all NZBs being reported as duplicates
|
||||
- Skin improvements
|
||||
|
||||
## Changes in Beta2
|
||||
- Improvements in IPv6 handling
|
||||
- Extension of SSL protocols (where supported)
|
||||
- Many improvemnts in the Glitter skin
|
||||
- On Windows, Season Sort often failed
|
||||
- Speedlimiting can now be absolute or in percentage
|
||||
- Scheduler action to remove completed history items
|
||||
|
||||
## Changes in Beta1
|
||||
- Glitter is now the default skin
|
||||
- Glitter fixes and improvements
|
||||
- Removed Classic and Mobile skins
|
||||
- Removed Config parts of smpl and Plush skins
|
||||
- API-call "history" now accepts one or more "category" parameters in order to filter.
|
||||
- API-call "addurl" now returns a list of nzo_id's, which will be valid for the actual jobs.
|
||||
- Update unrar to release 5.21
|
||||
- Enable renaming of Usenet servers.
|
||||
- Add Pushbullet support.
|
||||
- Implement Pushover support.
|
||||
- Restore Rating function
|
||||
- Newsserver IPv6 load balancing aka Happy Eyeballs / RFC 6555
|
||||
- Lots of bug fixes
|
||||
|
||||
## Changes in Alpha3
|
||||
- New skin: Glitter
|
||||
- Assign servers to categories
|
||||
- When upgrading from 0.7.x, a backup server will get priority 1
|
||||
- Lots of bug fixes
|
||||
|
||||
## Changes in Alpha2
|
||||
- Server priorities instead of primary/backup ==> REVIEW YOUR SERVER SETTINGS!
|
||||
- Work-arounds to avoid bugs in PyOpenSSL 0.14
|
||||
- Support RAR's REV files to some extent
|
||||
- Diagnostic dashboard tab for "Status" page
|
||||
## Bugfixes in 1.0.2
|
||||
- Fix hangups at 100% when QuickCheck is off and "all-pars" is on
|
||||
- Fix handling of "too many connections" for some Usenet servers
|
||||
|
||||
|
||||
## What's new in 0.8.0
|
||||
## What's new in 1.0.1
|
||||
- Prevent creating orphan items in "incomplete" when deleting downloading jobs.
|
||||
- Forced item with missing articles caused overflow into paused jobs
|
||||
- Do QuickCheck even on files that would be removed by the Cleanup-list (problematic for RAR files).
|
||||
- Fix "Download all par2 files" behavior
|
||||
- Treat ambiguous numeric values as number of minutes for custom pause time.
|
||||
- Accept MIME records that have only LF line endings (error in some third-party utilities)
|
||||
- Fix PushOver support.
|
||||
- Fix breaking Glitter bug with large script_log
|
||||
- Fix issues with deleting jobs via the API
|
||||
- Fix issue where Sonarr could not read using the History-API
|
||||
- Increase default cache to 450M
|
||||
- The pre-queue script can now return an accept value of 2, meaning immediate failure. (Useful for Sonarr.)
|
||||
- Add start script for portable Windows installations
|
||||
|
||||
## What's new in 1.0.0
|
||||
- Full Unicode support with Chinese and Russian translations
|
||||
- Improved Notifications (including Prowl)
|
||||
- New default UI: Glitter
|
||||
- Server priorities instead of primary/backup ==> REVIEW YOUR SERVER SETTINGS!
|
||||
- Newsserver IPv6 load balancing aka Happy Eyeballs / RFC 6555
|
||||
- Duplicate detection for series
|
||||
- Bonjour/ZeroConfig support
|
||||
- More filters in RSS
|
||||
- 7zip support
|
||||
- Option to save repair time by downloading all par2 files
|
||||
- Support for long paths in Windows (above 260)
|
||||
- Improved security for external access
|
||||
- Lots of small improvements and bug fixes
|
||||
- The "Classic" skin is gone
|
||||
- Redesign of notifications classes
|
||||
- More notification services supported
|
||||
- Diagnostic dashboard tab for "Status" page
|
||||
- Bonjour/ZeroConfig support
|
||||
|
||||
## Remarks
|
||||
- SABnzbd's webserver now doesn't listen to IPv6 addresses by default.
|
||||
- Use Config->Special->ipv6_hosting if you want this enabled.
|
||||
- "localhost" will be replaced with "127.0.0.1", check any browser bookmark and third-party tool
|
||||
- Classic skin has been removed
|
||||
- Support extra parameters for par2 on other platforms than Windows
|
||||
- Option to verify HTTPS connections (default off)
|
||||
- Auto-negotiates best Usenet ssl protocol (override possible)
|
||||
- When upgrading from 0.7.x, a backup server will get priority 1
|
||||
|
||||
|
||||
## About
|
||||
SABnzbd is an open-source cross-platform binary newsreader.
|
||||
@@ -77,8 +59,8 @@ Release Notes - SABnzbd 0.8.0Beta4
|
||||
(c) Copyright 2007-2016 by "The SABnzbd-team" \<team@sabnzbd.org\>
|
||||
|
||||
|
||||
### IMPORTANT INFORMATION about release 0.8.0
|
||||
<http://wiki.sabnzbd.org/introducing-0-8-0>
|
||||
### IMPORTANT INFORMATION about release 1.0.0
|
||||
<http://wiki.sabnzbd.org/introducing-1-0-0>
|
||||
|
||||
### Known problems and solutions
|
||||
- Read the file "ISSUES.txt"
|
||||
@@ -90,8 +72,7 @@ Release Notes - SABnzbd 0.8.0Beta4
|
||||
- Start SABnzbd
|
||||
|
||||
The organization of the download queue is different from older versions.
|
||||
0.8.x will not see the existing queue, but you can go to
|
||||
1.0.x will not see the existing queue, but you can go to
|
||||
Status->QueueRepair and "Repair" the old queue.
|
||||
Also, your sabnzbd.ini file will be upgraded, making it
|
||||
incompatible with releases older than 0.7.9
|
||||
|
||||
|
||||
53
SABnzbd.py
53
SABnzbd.py
@@ -278,7 +278,7 @@ def print_help():
|
||||
print " --log-all Log all article handling (for developers)"
|
||||
print " --console Force console logging for OSX app"
|
||||
print " --new Run a new instance of SABnzbd"
|
||||
print " --no_ipv6 Do not listen on IPv6 address [::1]"
|
||||
print " --ipv6_hosting <0|1> Listen on IPv6 address [::1]"
|
||||
|
||||
|
||||
def print_version():
|
||||
@@ -699,7 +699,7 @@ def get_webhost(cherryhost, cherryport, https_port):
|
||||
|
||||
def attach_server(host, port, cert=None, key=None, chain=None):
|
||||
""" Define and attach server, optionally HTTPS """
|
||||
if not (sabnzbd.cfg.no_ipv6() and '::1' in host):
|
||||
if sabnzbd.cfg.ipv6_hosting() or '::1' not in host:
|
||||
http_server = _cpwsgi_server.CPWSGIServer()
|
||||
http_server.bind_addr = (host, port)
|
||||
if cert and key:
|
||||
@@ -714,7 +714,10 @@ def is_sabnzbd_running(url, timeout=None):
|
||||
""" Return True when there's already a SABnzbd instance running. """
|
||||
try:
|
||||
url = '%s&mode=version' % (url)
|
||||
# Do this without certificate verification, few installations will have that
|
||||
prev = sabnzbd.set_https_verification(False)
|
||||
ver = sabnzbd.newsunpack.get_from_url(url, timeout=timeout)
|
||||
sabnzbd.set_https_verification(prev)
|
||||
return bool(ver and re.search(r'\d+\.\d+\.', ver))
|
||||
except:
|
||||
return False
|
||||
@@ -743,8 +746,10 @@ def check_for_sabnzbd(url, upload_nzbs, allow_browser=True):
|
||||
# Upload any specified nzb files to the running instance
|
||||
if upload_nzbs:
|
||||
from sabnzbd.utils.upload import upload_file
|
||||
prev = sabnzbd.set_https_verification(0)
|
||||
for f in upload_nzbs:
|
||||
upload_file(url, f)
|
||||
sabnzbd.set_https_verification(prev)
|
||||
else:
|
||||
# Launch the web browser and quit since sabnzbd is already running
|
||||
# Trim away everything after the final slash in the URL
|
||||
@@ -827,7 +832,7 @@ def commandline_handler(frozen=True):
|
||||
try:
|
||||
opts, args = getopt.getopt(info, "phdvncw:l:s:f:t:b:2:",
|
||||
['pause', 'help', 'daemon', 'nobrowser', 'clean', 'logging=',
|
||||
'weblogging=', 'server=', 'templates', 'no_ipv6',
|
||||
'weblogging=', 'server=', 'templates', 'ipv6_hosting=',
|
||||
'template2', 'browser=', 'config-file=', 'force',
|
||||
'version', 'https=', 'autorestarted', 'repair', 'repair-all',
|
||||
'log-all', 'no-login', 'pid=', 'new', 'sessions', 'console', 'pidfile=',
|
||||
@@ -905,7 +910,7 @@ def main():
|
||||
new_instance = False
|
||||
force_sessions = False
|
||||
osx_console = False
|
||||
no_ipv6 = False
|
||||
ipv6_hosting = None
|
||||
|
||||
_service, sab_opts, _serv_opts, upload_nzbs = commandline_handler()
|
||||
|
||||
@@ -996,9 +1001,9 @@ def main():
|
||||
elif opt in ('--console',):
|
||||
re_argv.append(opt)
|
||||
osx_console = True
|
||||
elif opt in ('--no_ipv6',):
|
||||
no_ipv6 = True
|
||||
|
||||
elif opt in ('--ipv6_hosting',):
|
||||
ipv6_hosting = arg
|
||||
|
||||
sabnzbd.MY_FULLNAME = os.path.normpath(os.path.abspath(sabnzbd.MY_FULLNAME))
|
||||
sabnzbd.MY_NAME = os.path.basename(sabnzbd.MY_FULLNAME)
|
||||
sabnzbd.DIR_PROG = os.path.dirname(sabnzbd.MY_FULLNAME)
|
||||
@@ -1075,8 +1080,8 @@ def main():
|
||||
# Set root folders for HTTPS server file paths
|
||||
sabnzbd.cfg.set_root_folders2()
|
||||
|
||||
if no_ipv6:
|
||||
sabnzbd.cfg.no_ipv6.set(True)
|
||||
if ipv6_hosting is not None:
|
||||
sabnzbd.cfg.ipv6_hosting.set(ipv6_hosting)
|
||||
|
||||
# Determine web host address
|
||||
cherryhost, cherryport, browserhost, https_port = get_webhost(cherryhost, cherryport, https_port)
|
||||
@@ -1237,6 +1242,7 @@ def main():
|
||||
|
||||
logging.info('--------------------------------')
|
||||
logging.info('%s-%s (rev=%s)', sabnzbd.MY_NAME, sabnzbd.__version__, sabnzbd.__baseline__)
|
||||
logging.info('Full executable path = %s', sabnzbd.MY_FULLNAME)
|
||||
if sabnzbd.WIN32:
|
||||
suffix = ''
|
||||
if vista_plus:
|
||||
@@ -1251,9 +1257,14 @@ def main():
|
||||
logging.info('Platform = %s', os.name)
|
||||
logging.info('Python-version = %s', sys.version)
|
||||
logging.info('Arguments = %s', sabnzbd.CMDLINE)
|
||||
try:
|
||||
logging.info('Preferred encoding = %s', locale.getpreferredencoding())
|
||||
except:
|
||||
logging.info('Preferred encoding = ERROR')
|
||||
|
||||
|
||||
if sabnzbd.cfg.log_level() > 1:
|
||||
from sabnzbd.utils.getipaddress import localipv4, publicipv4, ipv6
|
||||
from sabnzbd.getipaddress import localipv4, publicipv4, ipv6
|
||||
|
||||
mylocalipv4 = localipv4()
|
||||
if mylocalipv4:
|
||||
@@ -1359,6 +1370,7 @@ def main():
|
||||
|
||||
import sabnzbd.utils.sslinfo
|
||||
logging.info("SSL version %s", sabnzbd.utils.sslinfo.ssl_version())
|
||||
logging.info("pyOpenSSL version %s", sabnzbd.utils.sslinfo.pyopenssl_version())
|
||||
logging.info("SSL potentially supported protocols %s", str(sabnzbd.utils.sslinfo.ssl_potential()))
|
||||
logging.info("SSL actually supported protocols %s", str(sabnzbd.utils.sslinfo.ssl_protocols()))
|
||||
|
||||
@@ -1468,9 +1480,10 @@ def main():
|
||||
'error_page.404': sabnzbd.panic.error_page_404
|
||||
})
|
||||
|
||||
static = {'tools.staticdir.on': True, 'tools.staticdir.dir': os.path.join(web_dir, 'static')}
|
||||
staticcfg = {'tools.staticdir.on': True, 'tools.staticdir.dir': os.path.join(web_dirc, 'staticcfg')}
|
||||
wizard_static = {'tools.staticdir.on': True, 'tools.staticdir.dir': os.path.join(wizard_dir, 'static')}
|
||||
forced_mime_types = {'css': 'text/css', 'js': 'application/javascript'}
|
||||
static = {'tools.staticdir.on': True, 'tools.staticdir.dir': os.path.join(web_dir, 'static'), 'tools.staticdir.content_types': forced_mime_types}
|
||||
staticcfg = {'tools.staticdir.on': True, 'tools.staticdir.dir': os.path.join(web_dirc, 'staticcfg'), 'tools.staticdir.content_types': forced_mime_types}
|
||||
wizard_static = {'tools.staticdir.on': True, 'tools.staticdir.dir': os.path.join(wizard_dir, 'static'), 'tools.staticdir.content_types': forced_mime_types}
|
||||
|
||||
appconfig = {'/sabnzbd/api': {'tools.basic_auth.on': False},
|
||||
'/api': {'tools.basic_auth.on': False},
|
||||
@@ -1489,7 +1502,7 @@ def main():
|
||||
}
|
||||
|
||||
if web_dir2:
|
||||
static2 = {'tools.staticdir.on': True, 'tools.staticdir.dir': os.path.join(web_dir2, 'static')}
|
||||
static2 = {'tools.staticdir.on': True, 'tools.staticdir.dir': os.path.join(web_dir2, 'static'), 'tools.staticdir.content_types': forced_mime_types}
|
||||
appconfig['/sabnzbd/m/api'] = {'tools.basic_auth.on': False}
|
||||
appconfig['/sabnzbd/m/rss'] = {'tools.basic_auth.on': False}
|
||||
appconfig['/sabnzbd/m/shutdown'] = {'streamResponse': True}
|
||||
@@ -1671,16 +1684,20 @@ def main():
|
||||
sys.argv = re_argv
|
||||
os.chdir(org_dir)
|
||||
if sabnzbd.DARWIN:
|
||||
args = sys.argv[:]
|
||||
args.insert(0, sys.executable)
|
||||
# TODO: when executing from sources on osx, after a restart, process is detached from console
|
||||
# If OSX frozen restart of app instead of embedded python
|
||||
if getattr(sys, 'frozen', None) == 'macosx_app':
|
||||
# [[NSProcessInfo processInfo] processIdentifier]]
|
||||
# logging.info("%s" % (NSProcessInfo.processInfo().processIdentifier()))
|
||||
logging.info(os.getpid())
|
||||
os.system('kill -9 %s && open "%s"' % (os.getpid(), sabnzbd.MY_FULLNAME.replace("/Contents/MacOS/SABnzbd", "")))
|
||||
my_pid = os.getpid()
|
||||
my_name = sabnzbd.MY_FULLNAME.replace('/Contents/MacOS/SABnzbd', '')
|
||||
my_args = ' '.join(sys.argv[1:])
|
||||
cmd = 'kill -9 %s && open "%s" --args %s' % (my_pid, my_name, my_args)
|
||||
logging.info('Launching: ', cmd)
|
||||
os.system(cmd)
|
||||
else:
|
||||
args = sys.argv[:]
|
||||
args.insert(0, sys.executable)
|
||||
pid = os.fork()
|
||||
if pid == 0:
|
||||
os.execv(sys.executable, args)
|
||||
|
||||
@@ -608,10 +608,10 @@ class Part(Entity):
|
||||
# No more data--illegal end of headers
|
||||
raise EOFError("Illegal end of headers.")
|
||||
|
||||
if line == ntob('\r\n'):
|
||||
if line == ntob('\r\n') or line == ntob('\n'):
|
||||
# Normal end of headers
|
||||
break
|
||||
if not line.endswith(ntob('\r\n')):
|
||||
if not line.endswith(ntob('\n')):
|
||||
raise ValueError("MIME requires CRLF terminators: %r" % line)
|
||||
|
||||
if line[0] in ntob(' \t'):
|
||||
|
||||
@@ -442,7 +442,13 @@ class Bus(object):
|
||||
def log(self, msg="", level=20, traceback=False):
|
||||
"""Log the given message. Append the last traceback if requested."""
|
||||
if traceback:
|
||||
msg += "\n" + "".join(_traceback.format_exception(*sys.exc_info()))
|
||||
# Work-around for bug in Python's traceback implementation
|
||||
# which crashes when the error message contains %1, %2 etc.
|
||||
errors = sys.exc_info()
|
||||
if '%' in errors[1].message:
|
||||
errors[1].message = errors[1].message.replace('%', '#')
|
||||
errors[1].args = [item.replace('%', '#') for item in errors[1].args]
|
||||
msg += "\n" + "".join(_traceback.format_exception(*errors))
|
||||
self.publish('log', msg, level)
|
||||
|
||||
bus = Bus()
|
||||
|
||||
@@ -1,60 +1,117 @@
|
||||
<!--#set global $pane="Config"#-->
|
||||
<!--#set global $help_uri="configure-0-7"#-->
|
||||
<!--#set global $help_uri="configure-1-0"#-->
|
||||
<!--#include $webdir + "/_inc_header_uc.tmpl"#-->
|
||||
<div class="colmask">
|
||||
<div class="section padTable">
|
||||
<table id="infoTable">
|
||||
<tbody>
|
||||
<tr class="alt">
|
||||
<td class="infoTableHeader">$T('version'): </td>
|
||||
<td class="infoTableCell">$version [$build]</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td class="infoTableHeader">$T('uptime'): </td>
|
||||
<td class="infoTableCell">$uptime</td>
|
||||
</tr>
|
||||
<tr class="alt">
|
||||
<td class="infoTableHeader">$T('confgFile'): </td>
|
||||
<td class="infoTableCell">$configfn</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td class="infoTableHeader">$T('cache').capitalize(): </td>
|
||||
<td class="infoTableCell"><!--#set $msg=$T('ft-buffer@2')%($cache_art, $cache_size)#-->$msg</td>
|
||||
</tr>
|
||||
<tr class="alt">
|
||||
<td class="infoTableHeader">$T('parameters'): </td>
|
||||
<td class="infoTableCell">$cmdline</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td class="infoTableHeader">$T('pythonVersion'): </td>
|
||||
<td class="infoTableCell">$sys.version[:120]</td>
|
||||
</tr>
|
||||
<tr class="infoTableSeperator alt">
|
||||
<td class="infoTableHeader">$T('homePage') </td>
|
||||
<td class="infoTableCell"><a href="http://sabnzbd.org/" target="_blank">http://sabnzbd.org/</a></td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td class="infoTableHeader">$T('menu-wiki') </td>
|
||||
<td class="infoTableCell"><a href="http://wiki.sabnzbd.org/faq" target="_blank">http://wiki.sabnzbd.org/faq</a></td>
|
||||
</tr>
|
||||
<tr class="alt">
|
||||
<td class="infoTableHeader">$T('menu-forums') </td>
|
||||
<td class="infoTableCell"><a href="http://forums.sabnzbd.org/" target="_blank">http://forums.sabnzbd.org/</a></td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td class="infoTableHeader">$T('source') </td>
|
||||
<td class="infoTableCell"><a href="https://github.com/sabnzbd/sabnzbd" target="_blank">https://github.com/sabnzbd/sabnzbd</a></td>
|
||||
</tr>
|
||||
<tr class="alt">
|
||||
<td class="infoTableHeader">$T('menu-irc') </td>
|
||||
<td class="infoTableCell"><a href="irc://irc.synirc.net/#sabnzbd"><i>#sabnzbd</i> on <i>irc.synirc.net</i></a> $T('or') (<a href="http://sabnzbd.org/live-chat/" target="_blank">webchat</a>)</td>
|
||||
</tr>
|
||||
</tbody>
|
||||
</table>
|
||||
|
||||
<!--#from sabnzbd.newswrapper import HAVE_SSL#-->
|
||||
<!--#import sabnzbd.utils.sslinfo#-->
|
||||
<!--#from sabnzbd.decoder import HAVE_YENC#-->
|
||||
<!--#from sabnzbd.newsunpack import PAR2_COMMAND, PAR2C_COMMAND, RAR_COMMAND, ZIP_COMMAND, SEVEN_COMMAND, NICE_COMMAND, IONICE_COMMAND#-->
|
||||
|
||||
<div class="colmask">
|
||||
<div class="section padTable">
|
||||
<table class="table table-striped">
|
||||
<tbody>
|
||||
<tr>
|
||||
<th scope="row">$T('version'): </th>
|
||||
<td>$version [$build]</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<th scope="row">$T('uptime'): </th>
|
||||
<td>$uptime</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<th scope="row">$T('confgFile'): </th>
|
||||
<td>$configfn</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<th scope="row">$T('cache').capitalize(): </th>
|
||||
<td><!--#set $msg=$T('ft-buffer@2')%($cache_art, $cache_size)#-->$msg</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<th scope="row">$T('parameters'): </th>
|
||||
<td>$cmdline</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<th scope="row">$T('pythonVersion'): </th>
|
||||
<td>$sys.version[:120]</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<th scope="row">OpenSSL:</th>
|
||||
<td>
|
||||
<!--#if HAVE_SSL#-->
|
||||
<!--#set $sslversions = ', '.join(sabnzbd.utils.sslinfo.ssl_protocols())#-->
|
||||
$sabnzbd.utils.sslinfo.ssl_version() <em>[$sslversions]</em>
|
||||
<!--#else#-->
|
||||
<span class="label label-warning">$T('notAvailable')</span>
|
||||
<a href="$helpuri$help_uri#no_ssl" target="_blank"><span class="glyphicon glyphicon-question-sign"></span></a>
|
||||
<!--#end if#-->
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<th scope="row">pyOpenSSL:</th>
|
||||
<td>
|
||||
<!--#if HAVE_SSL#-->
|
||||
$sabnzbd.utils.sslinfo.pyopenssl_version()
|
||||
<!--#else#-->
|
||||
<span class="label label-warning">$T('notAvailable')</span>
|
||||
<a href="$helpuri$help_uri#no_ssl" target="_blank"><span class="glyphicon glyphicon-question-sign"></span></a>
|
||||
<!--#end if#-->
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<th scope="row">yEnc:</th>
|
||||
<td>
|
||||
<!--#if HAVE_YENC#-->
|
||||
<span class="glyphicon glyphicon-ok"></span>
|
||||
<!--#else#-->
|
||||
<span class="label label-warning">$T('notAvailable')</span>
|
||||
<a href="$helpuri$help_uri#no_yenc" target="_blank"><span class="glyphicon glyphicon-question-sign"></span></a>
|
||||
<!--#end if#-->
|
||||
</td>
|
||||
</tr>
|
||||
</tbody>
|
||||
</table>
|
||||
</div>
|
||||
</div>
|
||||
<div class="padding alt">
|
||||
<h5 class="copyright">Copyright © 2008-2016 The SABnzbd Team <<a href="mailto:team@sabnzbd.org">team@sabnzbd.org</a>></h5>
|
||||
<p class="copyright"><small>$T('yourRights')</small></p>
|
||||
<div class="colmask">
|
||||
<div class="section padTable">
|
||||
<table class="table table-striped">
|
||||
<tbody>
|
||||
<tr>
|
||||
<th scope="row">$T('homePage') </th>
|
||||
<td><a href="http://sabnzbd.org/" target="_blank">http://sabnzbd.org/</a></td>
|
||||
</tr>
|
||||
<tr>
|
||||
<th scope="row">$T('menu-wiki') </th>
|
||||
<td><a href="http://wiki.sabnzbd.org/faq" target="_blank">http://wiki.sabnzbd.org/faq</a></td>
|
||||
</tr>
|
||||
<tr>
|
||||
<th scope="row">$T('menu-forums') </th>
|
||||
<td><a href="http://forums.sabnzbd.org/" target="_blank">http://forums.sabnzbd.org/</a></td>
|
||||
</tr>
|
||||
<tr>
|
||||
<th scope="row">$T('source') </th>
|
||||
<td><a href="https://github.com/sabnzbd/sabnzbd" target="_blank">https://github.com/sabnzbd/sabnzbd</a></td>
|
||||
</tr>
|
||||
<tr>
|
||||
<th scope="row">$T('menu-irc') </th>
|
||||
<td><a href="irc://irc.synirc.net/#sabnzbd"><i>#sabnzbd</i> on <i>irc.synirc.net</i></a> $T('or') (<a href="http://sabnzbd.org/live-chat/" target="_blank">webchat</a>)</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<th scope="row">$T('menu-issues') </th>
|
||||
<td><a href="http://wiki.sabnzbd.org/issues-1-0-0" target="_blank">http://wiki.sabnzbd.org/issues-1-0-0</a></td>
|
||||
</tr>
|
||||
</tbody>
|
||||
</table>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="colmask">
|
||||
<div class="padding alt">
|
||||
<h5 class="copyright">Copyright © 2008-2016 The SABnzbd Team <<a href="mailto:team@sabnzbd.org">team@sabnzbd.org</a>></h5>
|
||||
<p class="copyright"><small>$T('yourRights')</small></p>
|
||||
</div>
|
||||
|
||||
</div>
|
||||
|
||||
<!--#include $webdir + "/_inc_footer_uc.tmpl"#-->
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
<!--#set global $pane="Categories"#-->
|
||||
<!--#set global $help_uri="configure-categories-0-7"#-->
|
||||
<!--#set global $help_uri="configure-categories-1-0"#-->
|
||||
<!--#include $webdir + "/_inc_header_uc.tmpl"#-->
|
||||
<div class="colmask">
|
||||
<div class="section">
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
<!--#set global $pane="Folders"#-->
|
||||
<!--#set global $help_uri="configure-folders-0-7"#-->
|
||||
<!--#set global $help_uri="configure-folders-1-0"#-->
|
||||
<!--#include $webdir + "/_inc_header_uc.tmpl"#-->
|
||||
|
||||
<div class="colmask">
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
<!--#set global $pane="General"#-->
|
||||
<!--#set global $help_uri="configure-general-0-8"#-->
|
||||
<!--#set global $help_uri="configure-general-1-0"#-->
|
||||
<!--#include $webdir + "/_inc_header_uc.tmpl"#-->
|
||||
|
||||
<div class="colmask">
|
||||
@@ -49,6 +49,7 @@
|
||||
<div class="field-pair">
|
||||
<label class="config" for="web_dir2">$T('opt-web_dir2')</label>
|
||||
<select name="web_dir2" id="web_dir2">
|
||||
<option value="None" selected="selected">$T("None")</option>
|
||||
<!--#for $webline in $web_list#-->
|
||||
<!--#if $webline.lower() == $web_dir2.lower()#-->
|
||||
<option value="$webline" selected="selected">$webline</option>
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
<!--#set global $pane="Email"#-->
|
||||
<!--#set global $help_uri="configure-notifications-0-8"#-->
|
||||
<!--#set global $help_uri="configure-notifications-1-0"#-->
|
||||
<!--#include $webdir + "/_inc_header_uc.tmpl"#-->
|
||||
|
||||
<div class="colmask">
|
||||
@@ -82,11 +82,6 @@
|
||||
</div><!-- /col2 -->
|
||||
<div class="col1" <!--#if int($ncenter_enable) > 0 then '' else 'style="display:none"'#-->>
|
||||
<fieldset>
|
||||
<div class="field-pair">
|
||||
<label class="config wide" for="ncenter_enable">$T('opt-ncenter_enable')</label>
|
||||
<input type="checkbox" name="ncenter_enable" id="ncenter_enable" value="1" <!--#if int($ncenter_enable) > 0 then 'checked="checked"' else ""#--> />
|
||||
<span class="desc">$T('explain-ncenter_enable')</span>
|
||||
</div>
|
||||
<div class="field-pair">
|
||||
<label class="config wide" for="ncenter_prio_startup">$T($notify_texts['startup']).replace('/', ' / ')</label>
|
||||
<input type="checkbox" name="ncenter_prio_startup" id="ncenter_prio_startup" value="1" <!--#if int($ncenter_prio_startup) > 0 then 'checked="checked"' else ""#--> />
|
||||
@@ -490,7 +485,7 @@
|
||||
<input type="text" name="pushover_userkey" id="pushover_userkey" value="$pushover_userkey" />
|
||||
<span class="desc">$T('explain-pushover_userkey')</span>
|
||||
</div>
|
||||
<div class="field-pair" style="display:none">
|
||||
<div class="field-pair">
|
||||
<label class="config" for="pushover_device">$T('opt-pushover_device')</label>
|
||||
<input type="text" name="pushover_device" id="pushover_device" value="$pushover_device" />
|
||||
<span class="desc">$T('explain-pushover_device')</span>
|
||||
@@ -498,91 +493,111 @@
|
||||
<div class="field-pair">
|
||||
<label class="config" for="pushover_prio_startup">$T($notify_texts['startup']).replace('/', ' / ')</label>
|
||||
<select name="pushover_prio_startup" id="pushover_prio_startup">
|
||||
<option value="-2" <!--#if $pushover_prio_startup == -2 then 'selected="selected"' else ""#--> >$T('pushover-off')</option>
|
||||
<option value="-3" <!--#if $pushover_prio_startup == -3 then 'selected="selected"' else ""#--> >$T('pushover-off')</option>
|
||||
<option value="-2" <!--#if $pushover_prio_startup == -2 then 'selected="selected"' else ""#--> >$T('prowl-very-low')</option>
|
||||
<option value="-1" <!--#if $pushover_prio_startup == -1 then 'selected="selected"' else ""#--> >$T('pushover-low')</option>
|
||||
<option value="0" <!--#if $pushover_prio_startup == 0 then 'selected="selected"' else ""#--> >$T('prowl-normal')</option>
|
||||
<option value="1" <!--#if $pushover_prio_startup == 1 then 'selected="selected"' else ""#--> >$T('pushover-high')</option>
|
||||
<option value="2" <!--#if $pushover_prio_startup == 2 then 'selected="selected"' else ""#--> >$T('pushover-confirm')</option>
|
||||
<option value="2" <!--#if $pushover_prio_startup == 2 then 'selected="selected"' else ""#--> >$T('prowl-emergency')</option>
|
||||
</select>
|
||||
</div>
|
||||
<div class="field-pair">
|
||||
<label class="config" for="pushover_prio_download">$T($notify_texts['download']) / $T('link-pause') / $T('link-resume')</label>
|
||||
<select name="pushover_prio_download" id="pushover_prio_download">
|
||||
<option value="-2" <!--#if $pushover_prio_download == -2 then 'selected="selected"' else ""#--> >$T('pushover-off')</option>
|
||||
<option value="-3" <!--#if $pushover_prio_download == -3 then 'selected="selected"' else ""#--> >$T('pushover-off')</option>
|
||||
<option value="-2" <!--#if $pushover_prio_download == -2 then 'selected="selected"' else ""#--> >$T('prowl-very-low')</option>
|
||||
<option value="-1" <!--#if $pushover_prio_download == -1 then 'selected="selected"' else ""#--> >$T('pushover-low')</option>
|
||||
<option value="0" <!--#if $pushover_prio_download == 0 then 'selected="selected"' else ""#--> >$T('prowl-normal')</option>
|
||||
<option value="1" <!--#if $pushover_prio_download == 1 then 'selected="selected"' else ""#--> >$T('pushover-high')</option>
|
||||
<option value="2" <!--#if $pushover_prio_download == 2 then 'selected="selected"' else ""#--> >$T('pushover-confirm')</option>
|
||||
<option value="2" <!--#if $pushover_prio_download == 2 then 'selected="selected"' else ""#--> >$T('prowl-emergency')</option>
|
||||
</select>
|
||||
</div>
|
||||
<div class="field-pair">
|
||||
<label class="config" for="pushover_prio_pp">$T($notify_texts['pp'])</label>
|
||||
<select name="pushover_prio_pp" id="pushover_prio_pp">
|
||||
<option value="-2" <!--#if $pushover_prio_pp == -2 then 'selected="selected"' else ""#--> >$T('pushover-off')</option>
|
||||
<option value="-3" <!--#if $pushover_prio_pp == -3 then 'selected="selected"' else ""#--> >$T('pushover-off')</option>
|
||||
<option value="-2" <!--#if $pushover_prio_pp == -2 then 'selected="selected"' else ""#--> >$T('prowl-very-low')</option>
|
||||
<option value="-1" <!--#if $pushover_prio_pp == -1 then 'selected="selected"' else ""#--> >$T('pushover-low')</option>
|
||||
<option value="0" <!--#if $pushover_prio_pp == 0 then 'selected="selected"' else ""#--> >$T('prowl-normal')</option>
|
||||
<option value="1" <!--#if $pushover_prio_pp == 1 then 'selected="selected"' else ""#--> >$T('pushover-high')</option>
|
||||
<option value="2" <!--#if $pushover_prio_pp == 2 then 'selected="selected"' else ""#--> >$T('pushover-confirm')</option>
|
||||
<option value="2" <!--#if $pushover_prio_pp == 2 then 'selected="selected"' else ""#--> >$T('prowl-emergency')</option>
|
||||
</select>
|
||||
</div>
|
||||
<div class="field-pair">
|
||||
<label class="config" for="pushover_prio_complete">$T($notify_texts['complete'])</label>
|
||||
<select name="pushover_prio_complete" id="pushover_prio_complete">
|
||||
<option value="-2" <!--#if $pushover_prio_complete == -2 then 'selected="selected"' else ""#--> >$T('pushover-off')</option>
|
||||
<option value="-3" <!--#if $pushover_prio_complete == -3 then 'selected="selected"' else ""#--> >$T('pushover-off')</option>
|
||||
<option value="-2" <!--#if $pushover_prio_complete == -2 then 'selected="selected"' else ""#--> >$T('prowl-very-low')</option>
|
||||
<option value="-1" <!--#if $pushover_prio_complete == -1 then 'selected="selected"' else ""#--> >$T('pushover-low')</option>
|
||||
<option value="0" <!--#if $pushover_prio_complete == 0 then 'selected="selected"' else ""#--> >$T('prowl-normal')</option>
|
||||
<option value="1" <!--#if $pushover_prio_complete == 1 then 'selected="selected"' else ""#--> >$T('pushover-high')</option>
|
||||
<option value="2" <!--#if $pushover_prio_complete == 2 then 'selected="selected"' else ""#--> >$T('pushover-confirm')</option>
|
||||
<option value="2" <!--#if $pushover_prio_complete == 2 then 'selected="selected"' else ""#--> >$T('prowl-emergency')</option>
|
||||
</select>
|
||||
</div>
|
||||
<div class="field-pair">
|
||||
<label class="config" for="pushover_prio_failed">$T($notify_texts['failed'])</label>
|
||||
<select name="pushover_prio_failed" id="pushover_prio_failed">
|
||||
<option value="-2" <!--#if $pushover_prio_failed == -2 then 'selected="selected"' else ""#--> >$T('pushover-off')</option>
|
||||
<option value="-3" <!--#if $pushover_prio_failed == -3 then 'selected="selected"' else ""#--> >$T('pushover-off')</option>
|
||||
<option value="-2" <!--#if $pushover_prio_failed == -2 then 'selected="selected"' else ""#--> >$T('prowl-very-low')</option>
|
||||
<option value="-1" <!--#if $pushover_prio_failed == -1 then 'selected="selected"' else ""#--> >$T('pushover-low')</option>
|
||||
<option value="0" <!--#if $pushover_prio_failed == 0 then 'selected="selected"' else ""#--> >$T('prowl-normal')</option>
|
||||
<option value="1" <!--#if $pushover_prio_failed == 1 then 'selected="selected"' else ""#--> >$T('pushover-high')</option>
|
||||
<option value="2" <!--#if $pushover_prio_failed == 2 then 'selected="selected"' else ""#--> >$T('pushover-confirm')</option>
|
||||
<option value="2" <!--#if $pushover_prio_failed == 2 then 'selected="selected"' else ""#--> >$T('prowl-emergency')</option>
|
||||
</select>
|
||||
</div>
|
||||
<div class="field-pair">
|
||||
<label class="config" for="pushover_prio_queue_done">$T($notify_texts['queue_done'])</label>
|
||||
<select name="pushover_prio_queue_done" id="pushover_prio_queue_done">
|
||||
<option value="-2" <!--#if $pushover_prio_queue_done == -2 then 'selected="selected"' else ""#--> >$T('pushover-off')</option>
|
||||
<option value="-3" <!--#if $pushover_prio_queue_done == -3 then 'selected="selected"' else ""#--> >$T('pushover-off')</option>
|
||||
<option value="-2" <!--#if $pushover_prio_queue_done == -2 then 'selected="selected"' else ""#--> >$T('prowl-very-low')</option>
|
||||
<option value="-1" <!--#if $pushover_prio_queue_done == -1 then 'selected="selected"' else ""#--> >$T('pushover-low')</option>
|
||||
<option value="0" <!--#if $pushover_prio_queue_done == 0 then 'selected="selected"' else ""#--> >$T('prowl-normal')</option>
|
||||
<option value="1" <!--#if $pushover_prio_queue_done == 1 then 'selected="selected"' else ""#--> >$T('pushover-high')</option>
|
||||
<option value="2" <!--#if $pushover_prio_queue_done == 2 then 'selected="selected"' else ""#--> >$T('pushover-confirm')</option>
|
||||
<option value="2" <!--#if $pushover_prio_queue_done == 2 then 'selected="selected"' else ""#--> >$T('prowl-emergency')</option>
|
||||
</select>
|
||||
</div>
|
||||
<div class="field-pair">
|
||||
<label class="config" for="pushover_prio_disk_full">$T($notify_texts['disk_full'])</label>
|
||||
<select name="pushover_prio_disk_full" id="pushover_prio_disk_full">
|
||||
<option value="-2" <!--#if $pushover_prio_disk_full == -2 then 'selected="selected"' else ""#--> >$T('pushover-off')</option>
|
||||
<option value="-3" <!--#if $pushover_prio_disk_full == -3 then 'selected="selected"' else ""#--> >$T('pushover-off')</option>
|
||||
<option value="-2" <!--#if $pushover_prio_disk_full == -2 then 'selected="selected"' else ""#--> >$T('prowl-very-low')</option>
|
||||
<option value="-1" <!--#if $pushover_prio_disk_full == -1 then 'selected="selected"' else ""#--> >$T('pushover-low')</option>
|
||||
<option value="0" <!--#if $pushover_prio_disk_full == 0 then 'selected="selected"' else ""#--> >$T('prowl-normal')</option>
|
||||
<option value="1" <!--#if $pushover_prio_disk_full == 1 then 'selected="selected"' else ""#--> >$T('pushover-high')</option>
|
||||
<option value="2" <!--#if $pushover_prio_disk_full == 2 then 'selected="selected"' else ""#--> >$T('pushover-confirm')</option>
|
||||
<option value="2" <!--#if $pushover_prio_disk_full == 2 then 'selected="selected"' else ""#--> >$T('prowl-emergency')</option>
|
||||
</select>
|
||||
</div>
|
||||
<div class="field-pair">
|
||||
<label class="config" for="pushover_prio_warning">$T($notify_texts['warning'])</label>
|
||||
<select name="pushover_prio_warning" id="pushover_prio_warning">
|
||||
<option value="-2" <!--#if $pushover_prio_warning == -2 then 'selected="selected"' else ""#--> >$T('pushover-off')</option>
|
||||
<option value="-3" <!--#if $pushover_prio_warning == -3 then 'selected="selected"' else ""#--> >$T('pushover-off')</option>
|
||||
<option value="-2" <!--#if $pushover_prio_warning == -2 then 'selected="selected"' else ""#--> >$T('prowl-very-low')</option>
|
||||
<option value="-1" <!--#if $pushover_prio_warning == -1 then 'selected="selected"' else ""#--> >$T('pushover-low')</option>
|
||||
<option value="0" <!--#if $pushover_prio_warning == 0 then 'selected="selected"' else ""#--> >$T('prowl-normal')</option>
|
||||
<option value="1" <!--#if $pushover_prio_warning == 1 then 'selected="selected"' else ""#--> >$T('pushover-high')</option>
|
||||
<option value="2" <!--#if $pushover_prio_warning == 2 then 'selected="selected"' else ""#--> >$T('pushover-confirm')</option>
|
||||
<option value="2" <!--#if $pushover_prio_warning == 2 then 'selected="selected"' else ""#--> >$T('prowl-emergency')</option>
|
||||
</select>
|
||||
</div>
|
||||
<div class="field-pair">
|
||||
<label class="config" for="pushover_prio_error">$T($notify_texts['error'])</label>
|
||||
<select name="pushover_prio_error" id="pushover_prio_error">
|
||||
<option value="-2" <!--#if $pushover_prio_error == -2 then 'selected="selected"' else ""#--> >$T('pushover-off')</option>
|
||||
<option value="-3" <!--#if $pushover_prio_error == -3 then 'selected="selected"' else ""#--> >$T('pushover-off')</option>
|
||||
<option value="-2" <!--#if $pushover_prio_error == -2 then 'selected="selected"' else ""#--> >$T('prowl-very-low')</option>
|
||||
<option value="-1" <!--#if $pushover_prio_error == -1 then 'selected="selected"' else ""#--> >$T('pushover-low')</option>
|
||||
<option value="0" <!--#if $pushover_prio_error == 0 then 'selected="selected"' else ""#--> >$T('prowl-normal')</option>
|
||||
<option value="1" <!--#if $pushover_prio_error == 1 then 'selected="selected"' else ""#--> >$T('pushover-high')</option>
|
||||
<option value="2" <!--#if $pushover_prio_error == 2 then 'selected="selected"' else ""#--> >$T('pushover-confirm')</option>
|
||||
<option value="2" <!--#if $pushover_prio_error == 2 then 'selected="selected"' else ""#--> >$T('prowl-emergency')</option>
|
||||
</select>
|
||||
</div>
|
||||
<div class="field-pair">
|
||||
<label class="config" for="pushover_prio_other">$T($notify_texts['other'])</label>
|
||||
<select name="pushover_prio_other" id="pushover_prio_other">
|
||||
<option value="-2" <!--#if $pushover_prio_other == -2 then 'selected="selected"' else ""#--> >$T('pushover-off')</option>
|
||||
<option value="-3" <!--#if $pushover_prio_other == -3 then 'selected="selected"' else ""#--> >$T('pushover-off')</option>
|
||||
<option value="-2" <!--#if $pushover_prio_other == -2 then 'selected="selected"' else ""#--> >$T('prowl-very-low')</option>
|
||||
<option value="-1" <!--#if $pushover_prio_other == -1 then 'selected="selected"' else ""#--> >$T('pushover-low')</option>
|
||||
<option value="0" <!--#if $pushover_prio_other == 0 then 'selected="selected"' else ""#--> >$T('prowl-normal')</option>
|
||||
<option value="1" <!--#if $pushover_prio_other == 1 then 'selected="selected"' else ""#--> >$T('pushover-high')</option>
|
||||
<option value="2" <!--#if $pushover_prio_other == 2 then 'selected="selected"' else ""#--> >$T('pushover-confirm')</option>
|
||||
<option value="2" <!--#if $pushover_prio_other == 2 then 'selected="selected"' else ""#--> >$T('prowl-emergency')</option>
|
||||
</select>
|
||||
</div>
|
||||
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
<!--#set global $pane="RSS"#-->
|
||||
<!--#set global $help_uri="configure-rss-0-8"#-->
|
||||
<!--#set global $help_uri="configure-rss-1-0"#-->
|
||||
<!--#include $webdir + "/_inc_header_uc.tmpl"#-->
|
||||
<div class="colmask">
|
||||
<!--#if not $active_feed#-->
|
||||
@@ -7,7 +7,7 @@
|
||||
<div class="padTable">
|
||||
<a class="main-helplink" href="$helpuri$help_uri" target="_blank"><span class="glyphicon glyphicon-question-sign"></span></a>
|
||||
<p>$T('explain-RSS')</p>
|
||||
<form action="add_rss_feed" method="post" novalidate>
|
||||
<form action="add_rss_feed" method="post" autocomplete="off" novalidate>
|
||||
<input type="hidden" name="session" value="$session" />
|
||||
<table class="catTable">
|
||||
<tr>
|
||||
@@ -37,7 +37,7 @@
|
||||
<!--#if $rss#-->
|
||||
<div class="section">
|
||||
<div class="padTable">
|
||||
<form action="save_rss_feed" method="post" novalidate>
|
||||
<form action="save_rss_feed" method="post" autocomplete="off" novalidate>
|
||||
<input type="hidden" name="session" value="$session" />
|
||||
<table id="subscriptions">
|
||||
<tbody>
|
||||
@@ -51,7 +51,7 @@
|
||||
</td>
|
||||
<td class="title">
|
||||
<a href="?feed=$rss[$feed_item]['link']" class="subscription-title path feed <!--#if int($rss[$feed_item]['enable']) != 0 then 'feed_enabled' else 'feed_disabled'#-->">
|
||||
<div class="favicon" style="background-image: url(http://www.google.com/s2/favicons?domain=$rss[$feed_item]['baselink']&alt=feed);"></div> $feed_item
|
||||
<div class="favicon" style="background-image: url(https://www.google.com/s2/favicons?domain=$rss[$feed_item]['baselink']&alt=feed);"></div> $feed_item
|
||||
</a>
|
||||
</td>
|
||||
<td class="controls">
|
||||
@@ -73,7 +73,7 @@
|
||||
</form>
|
||||
<!--#if $feeds#-->
|
||||
<br/>
|
||||
<form action="rss_now" method="post" novalidate>
|
||||
<form action="rss_now" method="post" autocomplete="off" novalidate>
|
||||
<input type="hidden" name="session" value="$session" />
|
||||
<button type="submit" class="btn btn-default readAll"><span class="glyphicon glyphicon-sort"></span> $T('button-rssNow')</button>
|
||||
</form>
|
||||
@@ -82,7 +82,7 @@
|
||||
</div>
|
||||
<!--#end if#-->
|
||||
<div class="section">
|
||||
<form action="save_rss_rate" method="post">
|
||||
<form action="save_rss_rate" method="post" autocomplete="off">
|
||||
<input type="hidden" name="session" value="$session" />
|
||||
<div class="col1">
|
||||
<fieldset>
|
||||
@@ -279,7 +279,7 @@
|
||||
<!--#set $fnum = 0#-->
|
||||
<!--#for $filter in $rss[$feed].filters#-->
|
||||
<!--#set $odd = not $odd#-->
|
||||
<form action="upd_rss_filter" method="post">
|
||||
<form action="upd_rss_filter" method="post" autocomplete="off">
|
||||
<input type="hidden" name="session" value="$session" />
|
||||
<input type="hidden" name="index" value="$fnum" />
|
||||
<input type="hidden" name="feed" value="$feed" />
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
<!--#set global $pane="Scheduling"#-->
|
||||
<!--#set global $help_uri="configure-scheduling-0-8"#-->
|
||||
<!--#set global $help_uri="configure-scheduling-1-0"#-->
|
||||
<!--#include $webdir + "/_inc_header_uc.tmpl"#-->
|
||||
|
||||
<%
|
||||
@@ -17,7 +17,7 @@ else:
|
||||
<div class="col2">
|
||||
<h3>$T('addSchedule') <a href="$helpuri$help_uri" target="_blank"><span class="glyphicon glyphicon-question-sign"></span></a></h3>
|
||||
</div><!-- /col2 -->
|
||||
<form action="addSchedule" method="post">
|
||||
<form action="addSchedule" method="post" autocomplete="off">
|
||||
<input type="hidden" id="session" name="session" value="$session" />
|
||||
<div class="col1">
|
||||
<fieldset>
|
||||
@@ -48,12 +48,20 @@ else:
|
||||
<div class="field-pair">
|
||||
<label class="config" for="action">$T('sch-action')</label>
|
||||
<select name="action" id="action">
|
||||
<!--#for $action in $actions#-->
|
||||
<option value="$action">$actions_lng[$action]</option>
|
||||
<!--#end for#-->
|
||||
<optgroup label="$T('sch-action')">
|
||||
<!--#for $action in $actions#-->
|
||||
<option value="$action" data-action="" data-noarg="<!--#if $action is 'speedlimit' then 0 else 1#-->">$actions_lng[$action]</option>
|
||||
<!--#end for#-->
|
||||
</optgroup>
|
||||
<optgroup label="$T('cmenu-servers')">
|
||||
<!--#for $server in $actions_servers.keys()#-->
|
||||
<option value="$server" data-action="1"data-noarg="1">$T('sch-enable_server') "$actions_servers[$server]"</option>
|
||||
<option value="$server" data-action="0"data-noarg="1">$T('sch-disable_server') "$actions_servers[$server]"</option>
|
||||
<!--#end for#-->
|
||||
</optgroup>
|
||||
</select>
|
||||
</div>
|
||||
<div class="field-pair">
|
||||
<div class="field-pair" id="hidden_arguments" style="display: none">
|
||||
<label class="config" for="arguments">$T('sch-arguments')</label>
|
||||
<input type="text" name="arguments" id="arguments" class="select_width" />
|
||||
</div>
|
||||
@@ -97,5 +105,16 @@ else:
|
||||
</div><!-- /col1 -->
|
||||
</div><!-- /section -->
|
||||
</div><!-- /colmask -->
|
||||
|
||||
<script type="text/javascript">
|
||||
\$('#action').on('change', function() {
|
||||
// Set the action
|
||||
\$('#arguments').val((\$(this).find('option:selected').data('action')))
|
||||
// Arguments
|
||||
if(\$(this).find('option:selected').data('noarg')) {
|
||||
\$('#hidden_arguments').hide()
|
||||
} else {
|
||||
\$('#hidden_arguments').show()
|
||||
}
|
||||
})
|
||||
</script>
|
||||
<!--#include $webdir + "/_inc_footer_uc.tmpl"#-->
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
<!--#set global $pane="Servers"#-->
|
||||
<!--#set global $help_uri="configure-servers-0-8"#-->
|
||||
<!--#set global $help_uri="configure-servers-1-0"#-->
|
||||
<!--#include $webdir + "/_inc_header_uc.tmpl"#-->
|
||||
|
||||
<div class="colmask">
|
||||
@@ -62,6 +62,7 @@
|
||||
<label class="config" for="ssl_type">$T('srv-ssl_type')</label>
|
||||
<!--#if int($have_ssl) == 1#-->
|
||||
<select name="ssl_type" id="ssl_type">
|
||||
<option value="">$T('Default')</option>
|
||||
<!--#if 't12' in $ssl_protocols#-->
|
||||
<option value="t12">TLS v1.2</option>
|
||||
<!--#end if#-->
|
||||
@@ -71,9 +72,6 @@
|
||||
<!--#if 't1' in $ssl_protocols#-->
|
||||
<option value="t1">TLS v1</option>
|
||||
<!--#end if#-->
|
||||
<!--#if 'v23' in $ssl_protocols#-->
|
||||
<option value="v23">SSL v23</option>
|
||||
<!--#end if#-->
|
||||
<!--#if 'v3' in $ssl_protocols#-->
|
||||
<option value="v3">SSL v3</option>
|
||||
<!--#end if#-->
|
||||
@@ -98,7 +96,9 @@
|
||||
<label class="config" for="categories">$T('srv-categories')</label>
|
||||
<select name="categories" id="categories" multiple>
|
||||
<!--#for $cat in $cats#-->
|
||||
<option value="$cat" <!--#if $cat == "Default"#-->selected<!--#end if#-->>$cat</option>
|
||||
<option value="$cat" <!--#if $cat == "Default"#-->selected<!--#end if#-->>
|
||||
<!--#if $cat == "Default" then $T('Default') else $cat#-->
|
||||
</option>
|
||||
<!--#end for#-->
|
||||
</select>
|
||||
<span class="desc">$T('srv-explain-categories')</span>
|
||||
@@ -118,24 +118,25 @@
|
||||
</fieldset>
|
||||
</div><!-- /col1 -->
|
||||
</div><!-- /section -->
|
||||
</form>
|
||||
</form>
|
||||
|
||||
<!--#set $cur = 0#-->
|
||||
<!--#for $server in $servers#-->
|
||||
<!--#set $cur = $cur + 1#-->
|
||||
|
||||
<form action="saveServer" method="post" class="fullform" novalidate>
|
||||
<form action="saveServer" method="post" class="fullform" autocomplete="off" novalidate>
|
||||
<input type="hidden" name="session" value="$session" />
|
||||
<input type="hidden" name="server" value="$server['name']" />
|
||||
|
||||
<div class="section">
|
||||
<div class="col2">
|
||||
<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>
|
||||
<span class="label label-primary" data-priority="$server['priority']">$server['priority']</span>
|
||||
<span class="label label-primary" data-priority="$server['priority']">$T('srv-priority'):</span>
|
||||
|
||||
<!--#if int($server['enable']) != 0#-->
|
||||
<span class="label label-primary" data-priority="$server['priority']#-->">$server['priority']</span>
|
||||
<span class="label label-primary" data-priority="$server['priority']#-->">$T('srv-priority'):</span>
|
||||
<!--#end if#-->
|
||||
<table><tr>
|
||||
<td><input type="checkbox" class="toggleServerCheckbox" id="enable_$cur" rel="$server['name']" name="q_enable" value="1" <!--#if int($server['enable']) != 0 then 'checked="checked"' else ""#--> /></td>
|
||||
<td><input type="checkbox" class="toggleServerCheckbox" id="enable_$cur" name="$server['name']" value="1" <!--#if int($server['enable']) != 0 then 'checked="checked"' else ""#--> /></td>
|
||||
<td><label for="enable_$cur">$T('enabled')</label></td>
|
||||
</tr></table>
|
||||
|
||||
@@ -186,6 +187,7 @@
|
||||
<label class="config" for="ssl_type$cur">$T('srv-ssl_type')</label>
|
||||
<!--#if int($have_ssl) == 1#-->
|
||||
<select name="ssl_type" id="ssl_type$cur">
|
||||
<option value="" <!--#if $server['ssl_type'] == "" then 'selected="selected"' else ""#--> >$T('Default')</option>
|
||||
<!--#if 't12' in $ssl_protocols#-->
|
||||
<option value="t12" <!--#if $server['ssl_type'] == "t12" then 'selected="selected"' else ""#--> >TLS v1.2</option>
|
||||
<!--#end if#-->
|
||||
@@ -195,9 +197,6 @@
|
||||
<!--#if 't1' in $ssl_protocols#-->
|
||||
<option value="t1" <!--#if $server['ssl_type'] == "t1" then 'selected="selected"' else ""#--> >TLS v1</option>
|
||||
<!--#end if#-->
|
||||
<!--#if 'v23' in $ssl_protocols#-->
|
||||
<option value="v23" <!--#if $server['ssl_type'] == "v23" then 'selected="selected"' else ""#--> >SSL v23</option>
|
||||
<!--#end if#-->
|
||||
<!--#if 'v3' in $ssl_protocols#-->
|
||||
<option value="v3" <!--#if $server['ssl_type'] == "v3" then 'selected="selected"' else ""#--> >SSL v3</option>
|
||||
<!--#end if#-->
|
||||
@@ -222,7 +221,9 @@
|
||||
<label class="config" for="categories$cur">$T('srv-categories')</label>
|
||||
<select name="categories" id="categories$cur" multiple>
|
||||
<!--#for $cat in $cats#-->
|
||||
<option value="$cat" <!--#if $cat in $server['categories'] then 'selected' else ""#-->>$cat</option>
|
||||
<option value="$cat" <!--#if $cat in $server['categories'] then 'selected' else ""#-->>
|
||||
<!--#if $cat == "Default" then $T('Default') else $cat#-->
|
||||
</option>
|
||||
<!--#end for#-->
|
||||
</select>
|
||||
<span class="desc">$T('srv-explain-categories')</span>
|
||||
@@ -285,15 +286,13 @@
|
||||
\$(this).css('background-color', theColor)
|
||||
})
|
||||
|
||||
/**
|
||||
High-light disabled servers
|
||||
**/
|
||||
\$('.toggleServerCheckbox:not(:checked)').parents('.col2').addClass('server-disabled').find('.label').css('background-color', '#777')
|
||||
|
||||
/**
|
||||
Click events
|
||||
**/
|
||||
\$('.showserver').click(function () {
|
||||
if(\$(this).parent().hasClass('server-disabled')) {
|
||||
\$(this).parent().parent().toggleClass('server-disabled')
|
||||
}
|
||||
\$(this).parent().next().toggle();
|
||||
\$(this).parent().next().next().toggle();
|
||||
if (\$(this).attr("value") == "$T('showDetails')") {
|
||||
@@ -324,7 +323,7 @@
|
||||
// Let us leave!
|
||||
formWasSubmitted = true;
|
||||
formHasChanged = false;
|
||||
location.reload();
|
||||
setTimeout(function() { location.reload(); }, 100)
|
||||
}
|
||||
return false;
|
||||
});
|
||||
@@ -334,12 +333,12 @@
|
||||
// Let us leave!
|
||||
formWasSubmitted = true;
|
||||
formHasChanged = false;
|
||||
location.reload();
|
||||
setTimeout(function() { location.reload(); }, 100)
|
||||
}
|
||||
return false;
|
||||
});
|
||||
\$('.toggleServerCheckbox').click(function(){
|
||||
var whichServer = \$(this).attr("rel");
|
||||
var whichServer = \$(this).attr("name");
|
||||
\$.ajax({
|
||||
type: "POST",
|
||||
url: "toggleServer",
|
||||
@@ -348,7 +347,7 @@
|
||||
// Let us leave!
|
||||
formWasSubmitted = true;
|
||||
formHasChanged = false;
|
||||
location.reload();
|
||||
setTimeout(function() { location.reload(); }, 100)
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
@@ -1,9 +1,9 @@
|
||||
<!--#set global $pane="Sorting"#-->
|
||||
<!--#set global $help_uri="configure-sorting-0-7"#-->
|
||||
<!--#set global $help_uri="configure-sorting-1-0"#-->
|
||||
<!--#include $webdir + "/_inc_header_uc.tmpl"#-->
|
||||
|
||||
<div class="colmask">
|
||||
<form action="saveSorting" method="post" name="fullform" class="fullform">
|
||||
<form action="saveSorting" method="post" name="fullform" class="fullform" autocomplete="off">
|
||||
<input type="hidden" id="session" name="session" value="$session" />
|
||||
<input id="complete_dir" type="hidden" value="$complete_dir" />
|
||||
<div class="section">
|
||||
|
||||
@@ -1,9 +1,9 @@
|
||||
<!--#set global $pane="Special"#-->
|
||||
<!--#set global $help_uri="configure-special-0-8"#-->
|
||||
<!--#set global $help_uri="configure-special-1-0"#-->
|
||||
<!--#include $webdir + "/_inc_header_uc.tmpl"#-->
|
||||
|
||||
<div class="colmask">
|
||||
<form action="saveSpecial" method="post" name="fullform" class="fullform">
|
||||
<form action="saveSpecial" method="post" autocomplete="off">
|
||||
<input type="hidden" id="session" name="session" value="$session" />
|
||||
<div class="padTable">
|
||||
<h4 class="darkred nomargin">$T('explain-special')</h4>
|
||||
|
||||
@@ -1,9 +1,9 @@
|
||||
<!--#set global $pane="Switches"#-->
|
||||
<!--#set global $help_uri="configure-switches-0-8"#-->
|
||||
<!--#set global $help_uri="configure-switches-1-0"#-->
|
||||
<!--#include $webdir + "/_inc_header_uc.tmpl"#-->
|
||||
|
||||
<div class="colmask">
|
||||
<form action="saveSwitches" method="post" name="fullform" class="fullform">
|
||||
<form action="saveSwitches" method="post" name="fullform" class="fullform" autocomplete="off">
|
||||
<input type="hidden" id="session" name="session" value="$session" />
|
||||
<div class="section">
|
||||
<div class="col2">
|
||||
@@ -11,6 +11,11 @@
|
||||
</div><!-- /col2 -->
|
||||
<div class="col1">
|
||||
<fieldset>
|
||||
<div class="field-pair">
|
||||
<label class="config" for="auto_browser">$T('opt-auto_browser')</label>
|
||||
<input type="checkbox" name="auto_browser" id="auto_browser" value="1" <!--#if int($auto_browser) > 0 then 'checked="checked"' else ""#--> />
|
||||
<span class="desc">$T('explain-auto_browser')</span>
|
||||
</div>
|
||||
<div class="field-pair">
|
||||
<label class="config" for="check_new_rel">$T('opt-check_new_rel')</label>
|
||||
<select name="check_new_rel" id="check_new_rel">
|
||||
@@ -20,11 +25,6 @@
|
||||
</select>
|
||||
<span class="desc">$T('explain-check_new_rel')</span>
|
||||
</div>
|
||||
<div class="field-pair">
|
||||
<label class="config" for="auto_browser">$T('opt-auto_browser')</label>
|
||||
<input type="checkbox" name="auto_browser" id="auto_browser" value="1" <!--#if int($auto_browser) > 0 then 'checked="checked"' else ""#--> />
|
||||
<span class="desc">$T('explain-auto_browser')</span>
|
||||
</div>
|
||||
<div class="field-pair <!--#if not $have_ampm then "disabled" else "" #-->">
|
||||
<label class="config" for="ampm">$T('opt-ampm')</label>
|
||||
<input type="checkbox" name="ampm" id="ampm" value="1" <!--#if int($ampm) > 0 then 'checked="checked"' else ""#--> <!--#if not $have_ampm then 'readonly="readonly" disabled="disabled"' else "" #--> />
|
||||
@@ -79,15 +79,33 @@
|
||||
<div class="col1">
|
||||
<fieldset>
|
||||
<div class="field-pair">
|
||||
<label class="config" for="fail_hopeless">$T('opt-fail_hopeless')</label>
|
||||
<input type="checkbox" name="fail_hopeless" id="fail_hopeless" value="1" <!--#if int($fail_hopeless) > 0 then 'checked="checked"' else ""#--> />
|
||||
<span class="desc">$T('explain-fail_hopeless')</span>
|
||||
<label class="config" for="pre_script">$T('opt-pre_script')</label>
|
||||
<select name="pre_script" id="pre_script">
|
||||
<!--#for $sc in $script_list#-->
|
||||
<!--#if $sc.lower() == $pre_script.lower()#-->
|
||||
<option value="$sc" selected="selected">$Tspec($sc)</option>
|
||||
<!--#else#-->
|
||||
<option value="$sc">$Tspec($sc)</option>
|
||||
<!--#end if#-->
|
||||
<!--#end for#-->
|
||||
</select>
|
||||
<span class="desc">$T('explain-pre_script')</span>
|
||||
</div>
|
||||
<div class="field-pair">
|
||||
<label class="config" for="top_only">$T('opt-top_only')</label>
|
||||
<input type="checkbox" name="top_only" id="top_only" value="1" <!--#if int($top_only) > 0 then 'checked="checked"' else ""#--> />
|
||||
<span class="desc">$T('explain-top_only')</span>
|
||||
</div>
|
||||
<div class="field-pair">
|
||||
<label class="config" for="pre_check">$T('opt-pre_check')</label>
|
||||
<input type="checkbox" name="pre_check" id="pre_check" value="1" <!--#if int($pre_check) > 0 then 'checked="checked"' else ""#--> />
|
||||
<span class="desc">$T('explain-pre_check')</span>
|
||||
</div>
|
||||
<div class="field-pair">
|
||||
<label class="config" for="fail_hopeless">$T('opt-fail_hopeless')</label>
|
||||
<input type="checkbox" name="fail_hopeless" id="fail_hopeless" value="1" <!--#if int($fail_hopeless) > 0 then 'checked="checked"' else ""#--> />
|
||||
<span class="desc">$T('explain-fail_hopeless')</span>
|
||||
</div>
|
||||
<div class="field-pair">
|
||||
<label class="config" for="no_dupes">$T('opt-no_dupes')</label>
|
||||
<select name="no_dupes" id="no_dupes">
|
||||
@@ -106,11 +124,6 @@
|
||||
</select>
|
||||
<span class="desc">$T('explain-no_series_dupes')</span>
|
||||
</div>
|
||||
<div class="field-pair">
|
||||
<label class="config" for="pause_on_post_processing">$T('opt-pause_on_post_processing')</label>
|
||||
<input type="checkbox" name="pause_on_post_processing" id="pause_on_post_processing" value="1" <!--#if int($pause_on_post_processing) > 0 then 'checked="checked"' else ""#--> />
|
||||
<span class="desc">$T('explain-pause_on_post_processing')</span>
|
||||
</div>
|
||||
<div class="field-pair">
|
||||
<label class="config" for="pause_on_pwrar">$T('opt-pause_on_pwrar')</label>
|
||||
<select name="pause_on_pwrar" id="pause_on_pwrar">
|
||||
@@ -134,29 +147,12 @@
|
||||
<input type="text" name="unwanted_extensions" id="unwanted_extensions" value="$unwanted_extensions"/>
|
||||
<span class="desc">$T('explain-unwanted_extensions')</span>
|
||||
</div>
|
||||
<div class="field-pair">
|
||||
<label class="config" for="top_only">$T('opt-top_only')</label>
|
||||
<input type="checkbox" name="top_only" id="top_only" value="1" <!--#if int($top_only) > 0 then 'checked="checked"' else ""#--> />
|
||||
<span class="desc">$T('explain-top_only')</span>
|
||||
</div>
|
||||
|
||||
<div class="field-pair">
|
||||
<label class="config" for="auto_sort">$T('opt-auto_sort')</label>
|
||||
<input type="checkbox" name="auto_sort" id="auto_sort" value="1" <!--#if int($auto_sort) > 0 then 'checked="checked"' else ""#--> />
|
||||
<span class="desc">$T('explain-auto_sort')</span>
|
||||
</div>
|
||||
<div class="field-pair">
|
||||
<label class="config" for="pre_script">$T('opt-pre_script')</label>
|
||||
<select name="pre_script" id="pre_script">
|
||||
<!--#for $sc in $script_list#-->
|
||||
<!--#if $sc.lower() == $pre_script.lower()#-->
|
||||
<option value="$sc" selected="selected">$Tspec($sc)</option>
|
||||
<!--#else#-->
|
||||
<option value="$sc">$Tspec($sc)</option>
|
||||
<!--#end if#-->
|
||||
<!--#end for#-->
|
||||
</select>
|
||||
<span class="desc">$T('explain-pre_script')</span>
|
||||
</div>
|
||||
<div class="field-pair">
|
||||
<button class="btn btn-default saveButton"><span class="glyphicon glyphicon-ok"></span> $T('button-saveChanges')</button>
|
||||
</div>
|
||||
@@ -170,22 +166,39 @@
|
||||
<div class="col1">
|
||||
<fieldset>
|
||||
<div class="field-pair">
|
||||
<label class="config" for="ignore_samples">$T('opt-ignore_samples')</label>
|
||||
<select name="ignore_samples" id="ignore_samples">
|
||||
<option value="0" <!--#if int($ignore_samples) == 0 then 'selected="selected"' else ""#--> >$T('igsam-off')</option>
|
||||
<option value="1" <!--#if int($ignore_samples) == 1 then 'selected="selected"' else ""#--> >$T('igsam-del')</option>
|
||||
</select>
|
||||
<span class="desc">$T('explain-ignore_samples')</span>
|
||||
<label class="config" for="pause_on_post_processing">$T('opt-pause_on_post_processing')</label>
|
||||
<input type="checkbox" name="pause_on_post_processing" id="pause_on_post_processing" value="1" <!--#if int($pause_on_post_processing) > 0 then 'checked="checked"' else ""#--> />
|
||||
<span class="desc">$T('explain-pause_on_post_processing')</span>
|
||||
</div>
|
||||
<div class="field-pair">
|
||||
<label class="config" for="enable_all_par">$T('opt-enable_all_par')</label>
|
||||
<input type="checkbox" name="enable_all_par" id="enable_all_par" value="1" <!--#if int($enable_all_par) > 0 then 'checked="checked"' else ""#--> />
|
||||
<span class="desc">$T('explain-enable_all_par')</span>
|
||||
</div>
|
||||
<div class="field-pair">
|
||||
<label class="config" for="quick_check">$T('opt-quick_check')</label>
|
||||
<input type="checkbox" name="quick_check" id="quick_check" value="1" <!--#if int($quick_check) > 0 then 'checked="checked"' else ""#--> />
|
||||
<span class="desc">$T('explain-quick_check')</span>
|
||||
</div>
|
||||
<div class="field-pair <!--#if not $have_multicore then "disabled" else "" #-->">
|
||||
<label class="config" for="par2_multicore">$T('opt-par2_multicore')</label>
|
||||
<input type="checkbox" name="par2_multicore" id="par2_multicore" value="1" <!--#if int($par2_multicore) > 0 then 'checked="checked"' else ""#--> <!--#if not $have_multicore then 'readonly="readonly" disabled="disabled"' else "" #--> />
|
||||
<span class="desc">$T('explain-par2_multicore')</span>
|
||||
</div>
|
||||
<div class="field-pair">
|
||||
<label class="config" for="enable_all_par">$T('opt-enable_all_par')</label>
|
||||
<input type="checkbox" name="enable_all_par" id="enable_all_par" value="1" <!--#if int($enable_all_par) > 0 then 'checked="checked"' else ""#--> />
|
||||
<span class="desc">$T('explain-enable_all_par')</span>
|
||||
<label class="config" for="par_option">$T('opt-par_option')</label>
|
||||
<input type="text" name="par_option" id="par_option" value="$par_option" />
|
||||
<span class="desc">$T('explain-par_option')</span>
|
||||
</div>
|
||||
<div class="field-pair">
|
||||
<label class="config" for="sfv_check">$T('opt-sfv_check')</label>
|
||||
<input type="checkbox" name="sfv_check" id="sfv_check" value="1" <!--#if int($sfv_check) > 0 then 'checked="checked"' else ""#--> />
|
||||
<span class="desc">$T('explain-sfv_check')</span>
|
||||
</div>
|
||||
<div class="field-pair">
|
||||
<label class="config" for="safe_postproc">$T('opt-safe_postproc')</label>
|
||||
<input type="checkbox" name="safe_postproc" id="safe_postproc" value="1" <!--#if int($safe_postproc) > 0 then 'checked="checked"' else ""#--> />
|
||||
<span class="desc">$T('explain-safe_postproc')</span>
|
||||
</div>
|
||||
<div class="field-pair <!--#if not $have_unrar then "disabled" else "" #-->">
|
||||
<label class="config" for="enable_unrar">$T('opt-enable_unrar')</label>
|
||||
@@ -227,21 +240,12 @@
|
||||
<input type="checkbox" name="enable_tsjoin" id="enable_tsjoin" value="1" <!--#if int($enable_tsjoin) > 0 then 'checked="checked"' else ""#--> />
|
||||
<span class="desc">$T('explain-ts_join')</span>
|
||||
</div>
|
||||
<div class="field-pair">
|
||||
<label class="config" for="safe_postproc">$T('opt-safe_postproc')</label>
|
||||
<input type="checkbox" name="safe_postproc" id="safe_postproc" value="1" <!--#if int($safe_postproc) > 0 then 'checked="checked"' else ""#--> />
|
||||
<span class="desc">$T('explain-safe_postproc')</span>
|
||||
</div>
|
||||
<div class="field-pair">
|
||||
<label class="config" for="sfv_check">$T('opt-sfv_check')</label>
|
||||
<input type="checkbox" name="sfv_check" id="sfv_check" value="1" <!--#if int($sfv_check) > 0 then 'checked="checked"' else ""#--> />
|
||||
<span class="desc">$T('explain-sfv_check')</span>
|
||||
</div>
|
||||
<div class="field-pair">
|
||||
<label class="config" for="unpack_check">$T('opt-unpack_check')</label>
|
||||
<input type="checkbox" name="unpack_check" id="unpack_check" value="1" <!--#if int($unpack_check) > 0 then 'checked="checked"' else ""#--> />
|
||||
<span class="desc">$T('explain-unpack_check')</span>
|
||||
</div>
|
||||
|
||||
<div class="field-pair">
|
||||
<label class="config" for="script_can_fail">$T('opt-script_can_fail')</label>
|
||||
<input type="checkbox" name="script_can_fail" id="script_can_fail" value="1" <!--#if int($script_can_fail) > 0 then 'checked="checked"' else ""#--> />
|
||||
@@ -252,16 +256,7 @@
|
||||
<input type="checkbox" name="new_nzb_on_failure" id="new_nzb_on_failure" value="1" <!--#if int($new_nzb_on_failure) > 0 then 'checked="checked"' else ""#--> />
|
||||
<span class="desc">$T('explain-new_nzb_on_failure')</span>
|
||||
</div>
|
||||
<div class="field-pair <!--#if not $have_multicore then "disabled" else "" #-->">
|
||||
<label class="config" for="par2_multicore">$T('opt-par2_multicore')</label>
|
||||
<input type="checkbox" name="par2_multicore" id="par2_multicore" value="1" <!--#if int($par2_multicore) > 0 then 'checked="checked"' else ""#--> <!--#if not $have_multicore then 'readonly="readonly" disabled="disabled"' else "" #--> />
|
||||
<span class="desc">$T('explain-par2_multicore')</span>
|
||||
</div>
|
||||
<div class="field-pair">
|
||||
<label class="config" for="par_option">$T('opt-par_option')</label>
|
||||
<input type="text" name="par_option" id="par_option" value="$par_option" />
|
||||
<span class="desc">$T('explain-par_option')</span>
|
||||
</div>
|
||||
<!--#if not $nt#-->
|
||||
<div class="field-pair <!--#if not $have_nice then "disabled" else "" #-->">
|
||||
<label class="config" for="nice">$T('opt-nice')</label>
|
||||
<input type="text" name="nice" id="nice" value="$nice" <!--#if not $have_nice then 'readonly="readonly" disabled="disabled"' else "" #--> />
|
||||
@@ -272,6 +267,12 @@
|
||||
<input type="text" name="ionice" id="ionice" value="$ionice" <!--#if not $have_ionice then 'readonly="readonly" disabled="disabled"' else "" #--> />
|
||||
<span class="desc">$T('explain-ionice')</span>
|
||||
</div>
|
||||
<!--#end if#-->
|
||||
<div class="field-pair">
|
||||
<label class="config" for="ignore_samples">$T('opt-ignore_samples')</label>
|
||||
<input type="checkbox" name="ignore_samples" id="ignore_samples" value="1" <!--#if int($ignore_samples) > 0 then 'checked="checked"' else ""#--> />
|
||||
<span class="desc">$T('explain-ignore_samples') $T('igsam-del').</span>
|
||||
</div>
|
||||
<div class="field-pair">
|
||||
<label class="config" for="cleanup_list">$T('opt-cleanup_list')</label>
|
||||
<input type="text" name="cleanup_list" id="cleanup_list" value="$cleanup_list"/>
|
||||
|
||||
@@ -262,6 +262,9 @@ textarea:hover, input[type="date"]:hover, input[type="datetime"]:hover, input[ty
|
||||
.padTable h3 {
|
||||
margin-top: 0;
|
||||
}
|
||||
tr.separator {
|
||||
height: 30px;
|
||||
}
|
||||
.catTable th, .catTable td {
|
||||
padding: 5px;
|
||||
}
|
||||
@@ -284,6 +287,28 @@ textarea:hover, input[type="date"]:hover, input[type="datetime"]:hover, input[ty
|
||||
.RSS form[action="add_rss_feed"] tr:nth-child(even) {
|
||||
border: 1px solid #E5E5E5;
|
||||
}
|
||||
.Config .table {
|
||||
margin: 0;
|
||||
border: 1px solid #ddd
|
||||
}
|
||||
.Config .colmask {
|
||||
margin-bottom: 12px;
|
||||
}
|
||||
.Config .padding {
|
||||
padding: 13px;
|
||||
}
|
||||
.Config th {
|
||||
width: 20%;
|
||||
min-width: 150px;
|
||||
padding-left: 15px !important;
|
||||
}
|
||||
.Config .label {
|
||||
font-size: 90%;
|
||||
}
|
||||
.Config td .glyphicon-question-sign {
|
||||
color: black !important;
|
||||
top: 3px;
|
||||
}
|
||||
.tab-pane thead tr {
|
||||
background-color: transparent !important;
|
||||
}
|
||||
@@ -715,6 +740,7 @@ input[type="text"].smaller_input {
|
||||
|
||||
select {
|
||||
min-width: 200px;
|
||||
max-width: 300px;
|
||||
}
|
||||
|
||||
input[disabled],
|
||||
@@ -801,6 +827,10 @@ input[type="checkbox"] {
|
||||
display: none;
|
||||
}
|
||||
|
||||
#navbar .glyphicon-folder-open {
|
||||
margin-right: 2px;
|
||||
}
|
||||
|
||||
.rss-icon-svg {
|
||||
display: inline-block;
|
||||
margin-top: 1px;
|
||||
@@ -824,6 +854,10 @@ input[type="checkbox"] {
|
||||
line-height: 1.1em;
|
||||
}
|
||||
|
||||
.Servers .col2.server-disabled .label {
|
||||
color: ##777 !important;
|
||||
}
|
||||
|
||||
.Servers .col2 .label:nth-child(2) {
|
||||
opacity: 0.7;
|
||||
}
|
||||
|
||||
@@ -50,7 +50,7 @@
|
||||
</a>
|
||||
<div class="dropdown-menu max-speed-input">
|
||||
<div data-bind="visible: !bandwithLimit()">
|
||||
<a href="config/general/#bandwidth_max">
|
||||
<a href="./config/general/#bandwidth_max">
|
||||
<span class="glyphicon glyphicon-cog"></span> $T('Glitter-setMaxLinespeed')
|
||||
</a>
|
||||
</div>
|
||||
@@ -70,7 +70,7 @@
|
||||
</li>
|
||||
<!--#if $have_rss_defined#-->
|
||||
<li data-tooltip="true" data-placement="bottom" title="$T('cmenu-rss')">
|
||||
<a href="config/rss">
|
||||
<a href="./config/rss/">
|
||||
<svg class="rss-icon-svg" viewBox="0 0 8 8">
|
||||
<rect class="rss-button" width="8" height="8" />
|
||||
<circle class="rss-symbol" cx="2" cy="6" r="1" />
|
||||
@@ -81,7 +81,7 @@
|
||||
</li>
|
||||
<!--#end if#-->
|
||||
<li data-tooltip="true" data-placement="bottom" title="SABnzbd $T('menu-config')">
|
||||
<a href="config"><span class="glyphicon glyphicon-cog"></span></a>
|
||||
<a href="./config/"><span class="glyphicon glyphicon-cog"></span></a>
|
||||
</li>
|
||||
<li class="dropdown main-menu-link" data-bind="css: { 'active-on-queue-finish-menu': onQueueFinish()}">
|
||||
<a href="#" data-toggle="dropdown" onclick="keepOpen(this)">
|
||||
@@ -97,7 +97,7 @@
|
||||
<!--#if $have_watched_dir#--><li><a href="#" data-bind="click: doQueueAction" data-mode="watched_now">$T('sch-scan_folder')</a></li><!--#end if#-->
|
||||
<!--#if $pp_pause_event#--><li><a href="#" data-bind="click: doQueueAction" data-mode="resume_pp">$T('sch-resume_post')</a></li><!--#end if#-->
|
||||
<li class="divider"></li>
|
||||
<li><a href="shutdown?session=$session" data-bind="click: shutdownSAB">$T('shutdownSab')</a></li>
|
||||
<li><a href="./shutdown/?session=$session" data-bind="click: shutdownSAB">$T('shutdownSab')</a></li>
|
||||
<li><a href="#" data-bind="click: restartSAB">$T('Glitter-restartSab')</a></li>
|
||||
<li class="divider"></li>
|
||||
<li class="dropdown-header"><span class="glyphicon glyphicon-off"></span> $T('Glitter-onFinish'):</li>
|
||||
|
||||
@@ -65,12 +65,21 @@
|
||||
<div class="col-sm-6">$T('dashboard-NameserverDNS')</div>
|
||||
<div class="col-sm-6" data-bind="text: !statusInfo.dashboard.dnslookup() ? '$T('dashboard-connectionError')' : statusInfo.dashboard.dnslookup(), css: { 'options-bad-status' : (statusInfo.dashboard.dnslookup() != 'OK') }"></div>
|
||||
</div>
|
||||
<hr/>
|
||||
<div class="row">
|
||||
<div class="col-sm-6">$T('dashboard-systemPerformance')</div>
|
||||
<div class="col-sm-6">
|
||||
<span data-bind="text: statusInfo.dashboard.pystone"></span>
|
||||
<a href="#" data-bind="click: loadStatusInfo" data-tooltip="true" data-placement="right" title="$T('dashboard-repeatTest')"><span class="glyphicon glyphicon-repeat"></span></a>
|
||||
<small data-bind="truncatedText: statusInfo.dashboard.cpumodel, length: 25"></small>
|
||||
</div>
|
||||
</div>
|
||||
<div class="row">
|
||||
<div class="col-sm-6">$T('dashboard-downloadDirSpeed')</div>
|
||||
<div class="col-sm-6">
|
||||
<span data-bind="text: (statusInfo.dashboard.downloaddirspeed() > 0 ? statusInfo.dashboard.downloaddirspeed() : '0'), css: { 'options-bad-status' : statusInfo.dashboard.downloaddirspeedbad() }"></span> MB/s
|
||||
<a href="#" data-bind="click: testDiskSpeed" data-tooltip="true" data-placement="right" title="$T('dashboard-repeatTest')"><span class="glyphicon glyphicon-repeat"></span></a>
|
||||
<small>(<span data-bind="truncatedText: statusInfo.dashboard.downloaddir, length: 25"></span>)</small>
|
||||
<small>(<span data-bind="truncatedText: statusInfo.dashboard.downloaddir, length: 24"></span>)</small>
|
||||
</div>
|
||||
</div>
|
||||
<div class="row">
|
||||
@@ -78,7 +87,7 @@
|
||||
<div class="col-sm-6">
|
||||
<span data-bind="text: (statusInfo.dashboard.completedirspeed() > 0 ? statusInfo.dashboard.completedirspeed() : '0'), css: { 'options-bad-status' : statusInfo.dashboard.completedirspeedbad() }"></span> MB/s
|
||||
<a href="#" data-bind="click: testDiskSpeed" data-tooltip="true" data-placement="right" title="$T('dashboard-repeatTest')"><span class="glyphicon glyphicon-repeat"></span></a>
|
||||
<small>(<span data-bind="truncatedText: statusInfo.dashboard.completedir, length: 25"></span>)</small>
|
||||
<small>(<span data-bind="truncatedText: statusInfo.dashboard.completedir, length: 24"></span>)</small>
|
||||
</div>
|
||||
</div>
|
||||
<div class="row">
|
||||
@@ -100,7 +109,7 @@
|
||||
</div>
|
||||
<div class="row options-function-box">
|
||||
<div class="col-sm-6">
|
||||
<a href="status/showlog?session=$session" target="_blank" class="btn btn-default"><span class="glyphicon glyphicon-file"></span> $T('link-showLog')</a>
|
||||
<a href="./status/showlog?session=$session" target="_blank" class="btn btn-default"><span class="glyphicon glyphicon-file"></span> $T('link-showLog')</a>
|
||||
</div>
|
||||
<div class="col-sm-6">
|
||||
<div class="input-group" data-tooltip="true" data-placement="top" title="$T('logging')">
|
||||
@@ -128,12 +137,20 @@
|
||||
</div>
|
||||
<div data-bind="foreach: statusInfo.status.servers">
|
||||
<div class="options-server-box">
|
||||
<a href="#" data-bind="visible: serverblocked(), click: function() { \$parent.unblockServer(servername()) }" class="btn btn-default">$T('Glitter-unblockServer')</a>
|
||||
|
||||
<div class="row">
|
||||
<div class="col-sm-6">$T('swtag-server')</div>
|
||||
<div class="col-sm-6">
|
||||
<span data-bind="text: servername"></span><br />
|
||||
<span data-bind="visible: serverblocked(), text: serverblocked" class="label label-danger"></span>
|
||||
<span data-bind="text: servername"></span>
|
||||
</div>
|
||||
</div>
|
||||
<div class="row" data-bind="visible: serverblocked()">
|
||||
<div class="col-sm-12">
|
||||
|
||||
<div class="alert alert-danger">
|
||||
<a href="#" data-bind="visible: serverblocked(), click: function() { \$parent.unblockServer(servername()) }" class="btn btn-default"><span class="glyphicon glyphicon-share-alt"></span> $T('Glitter-unblockServer')</a>
|
||||
<span data-bind="text: serverblocked()"></span>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="row">
|
||||
@@ -242,7 +259,7 @@
|
||||
<option value="40">40 / $T('Glitter-page')</option>
|
||||
<option value="50">50 / $T('Glitter-page')</option>
|
||||
<option value="100">100 / $T('Glitter-page')</option>
|
||||
<option value="9999999">$T('Glitter-everything')</option>
|
||||
<option value="250">250 / $T('Glitter-page')</option>
|
||||
</select>
|
||||
</div>
|
||||
</div>
|
||||
@@ -257,7 +274,7 @@
|
||||
<option value="40">40 / $T('Glitter-page')</option>
|
||||
<option value="50">50 / $T('Glitter-page')</option>
|
||||
<option value="100">100 / $T('Glitter-page')</option>
|
||||
<option value="9999999">$T('Glitter-everything')</option>
|
||||
<option value="250">250 / $T('Glitter-page')</option>
|
||||
</select>
|
||||
</div>
|
||||
</div>
|
||||
@@ -362,7 +379,7 @@
|
||||
<div class="row form-horizontal">
|
||||
<label class="col-sm-6 control-label">$T('Glitter-addnzbFilename')</label>
|
||||
<div class="col-sm-6">
|
||||
<input type="text" name="nzbname" id="nzbname" placeholder="$T('nzo-filename')" class="form-control" />
|
||||
<input type="text" name="nzbname" id="nzbname" placeholder="$T('name')" class="form-control" />
|
||||
</div>
|
||||
</div>
|
||||
<hr />
|
||||
@@ -479,7 +496,7 @@
|
||||
<span class="input-group-addon">
|
||||
<span class="glyphicon glyphicon-lock"></span>
|
||||
</span>
|
||||
<input type="text" class="form-control" id="retry_job_password" placeholder="$T('srv-password')" />
|
||||
<input type="text" class="form-control" id="retry_job_password" placeholder="$T('srv-password') ($T('srv-optional'))" />
|
||||
</div>
|
||||
</div>
|
||||
</fieldset>
|
||||
|
||||
@@ -2,9 +2,6 @@
|
||||
<h2>$T('menu-queue')</h2>
|
||||
|
||||
<div class="info-container" data-bind="visible: diskSpaceLeft1()" style="display: none;">
|
||||
<div class="info-container-box" id="localstorage-error">
|
||||
<span class="queue-error-info"></span>
|
||||
</div>
|
||||
<!-- ko if: hasWarnings() -->
|
||||
<div class="info-container-box">
|
||||
<a href="#queue-messages" class="queue-error-info">
|
||||
@@ -97,8 +94,8 @@
|
||||
<input type="text" data-bind="value: nameForEdit, visible: editingName(), hasfocus: editingName" />
|
||||
</form>
|
||||
<div class="name-options" data-bind="visible: !editingName()">
|
||||
<a href="#" data-bind="click: editName" class="hover-button"><span class="glyphicon glyphicon-pencil"></span></a>
|
||||
<a href="#" data-bind="click: showFiles" class="hover-button" title="$T('nzoDetails') - $T('srv-password')"><span class="glyphicon glyphicon-folder-open"></span></a>
|
||||
<a href="#" data-bind="click: editName, css: { disabled: isGrabbing() }" class="hover-button"><span class="glyphicon glyphicon-pencil"></span></a>
|
||||
<a href="#" data-bind="click: showFiles, css: { disabled: isGrabbing() }" class="hover-button" title="$T('nzoDetails') - $T('srv-password')"><span class="glyphicon glyphicon-folder-open"></span></a>
|
||||
<small data-bind="text: avg_age"></small>
|
||||
</div>
|
||||
</td>
|
||||
|
||||
@@ -21,7 +21,9 @@
|
||||
<meta name="application-name" content="SABnzbd">
|
||||
<meta name="apple-mobile-web-app-capable" content="yes" />
|
||||
<meta name="apple-mobile-web-app-title" content="SABnzbd" />
|
||||
<meta name="apple-mobile-web-app-status-bar-style" content="black" />
|
||||
<meta name="apple-mobile-web-app-status-bar-style" content="#000000" />
|
||||
<meta name="msapplication-navbutton-color" content="#000000" />
|
||||
<meta name="theme-color" content="#000000" />
|
||||
|
||||
<link rel="apple-touch-icon" sizes="76x76" href="./staticcfg/ico/apple-touch-icon-76x76-precomposed.png" />
|
||||
<link rel="apple-touch-icon" sizes="120x120" href="./staticcfg/ico/apple-touch-icon-120x120-precomposed.png" />
|
||||
@@ -59,7 +61,6 @@
|
||||
glitterTranslate.repair = "$T('explain-Repair')".replace(/<br \/>/g, "\n");
|
||||
glitterTranslate.removeDown = "$T('Glitter-confirmClearDownloads')";
|
||||
glitterTranslate.removeDow1 = "$T('Glitter-confirmClear1Download')";
|
||||
glitterTranslate.grabbing = "$T('Glitter-grabbing')";
|
||||
glitterTranslate.encrypted = "$T('Glitter-encrypted')";
|
||||
glitterTranslate.duplicate = "$T('Glitter-duplicate')";
|
||||
glitterTranslate.tooLarge = "$T('Glitter-tooLarge')";
|
||||
@@ -74,6 +75,7 @@
|
||||
glitterTranslate.chooseFile = "$T('Glitter-chooseFile')";
|
||||
glitterTranslate.orphanedJobsMsg = "$T('explain-orphans')";
|
||||
glitterTranslate.useCache = "$T('explain-cache_limitstr')";
|
||||
glitterTranslate.noLocalStorage = "$T('Glitter-noLocalStorage')";
|
||||
glitterTranslate.updateAvailable = "$T('Glitter-updateAvailable')";
|
||||
glitterTranslate.defaultText = "$T('default')";
|
||||
glitterTranslate.noneText = "$T('None')";
|
||||
@@ -98,6 +100,7 @@
|
||||
glitterTranslate.status['Script'] = "$T('stage-script')";
|
||||
glitterTranslate.status['Source'] = "$T('stage-source')";
|
||||
glitterTranslate.status['Servers'] = "$T('stage-servers')";
|
||||
glitterTranslate.status['INFO'] = "$T('log-info')".replace('+ ', '').toUpperCase();
|
||||
glitterTranslate.status['WARNING'] = "$T('Glitter-warning')";
|
||||
glitterTranslate.status['ERROR'] = "$T('Glitter-error')";
|
||||
|
||||
|
||||
@@ -11,8 +11,9 @@ var fadeOnDeleteDuration = 400; // ms after deleting a row
|
||||
var isMobile = (/android|webos|iphone|ipad|ipod|blackberry|iemobile|opera mini/i.test(navigator.userAgent.toLowerCase()));
|
||||
|
||||
// To avoid problems when localStorage is disabled
|
||||
function localStorageSetItem(varToSet, valueToSet) { try { return localStorage.setItem(varToSet, valueToSet); } catch(e) { $('#localstorage-error span').text('Cannot store settings locally'); } }
|
||||
function localStorageGetItem(varToGet) { try { return localStorage.getItem(varToGet); } catch(e) { $('#localstorage-error span').text('Cannot store settings locally'); } }
|
||||
var hasLocalStorage = true;
|
||||
function localStorageSetItem(varToSet, valueToSet) { try { return localStorage.setItem(varToSet, valueToSet); } catch(e) { hasLocalStorage = false; } }
|
||||
function localStorageGetItem(varToGet) { try { return localStorage.getItem(varToGet); } catch(e) { hasLocalStorage = false; } }
|
||||
|
||||
/**
|
||||
GLITTER CODE
|
||||
@@ -166,15 +167,15 @@ $(function() {
|
||||
var bandwithLimitText = self.bandwithLimit().replace(/[^a-zA-Z]+/g, '');
|
||||
|
||||
// Only the number
|
||||
var speedLimitNumber = (parseInt(self.bandwithLimit()) * (self.speedLimit() / 100));
|
||||
|
||||
var speedLimitNumberFull = (parseFloat(self.bandwithLimit()) * (self.speedLimit() / 100));
|
||||
|
||||
// Trick to only get decimal-point when needed
|
||||
speedLimitNumber = Math.round(speedLimitNumber*10)/10;
|
||||
var speedLimitNumber = Math.round(speedLimitNumberFull*10)/10;
|
||||
|
||||
// Fix it for lower than 1MB/s
|
||||
if(bandwithLimitText == 'M' && speedLimitNumber < 1) {
|
||||
bandwithLimitText = 'K';
|
||||
speedLimitNumber = Math.round(speedLimitNumber * 1024);
|
||||
speedLimitNumber = Math.round(speedLimitNumberFull * 1024);
|
||||
}
|
||||
|
||||
// Show text
|
||||
@@ -506,6 +507,12 @@ $(function() {
|
||||
|
||||
// Update on changes
|
||||
self.pauseCustom.subscribe(function(newValue) {
|
||||
// Is it plain numbers?
|
||||
if(newValue.match(/^\s*\d+\s*$/)) {
|
||||
// Treat it as a number of minutes
|
||||
newValue += " minutes";
|
||||
}
|
||||
|
||||
// At least 3 charaters
|
||||
if(newValue.length < 3) {
|
||||
$('#customPauseOutput').text('').data('time', 0)
|
||||
@@ -593,11 +600,10 @@ $(function() {
|
||||
});
|
||||
})
|
||||
|
||||
// Clear warnings through this weird URL..
|
||||
// Clear warnings through this special URL..
|
||||
self.clearWarnings = function() {
|
||||
if(!self.confirmDeleteQueue() || confirm(glitterTranslate.clearWarn))
|
||||
// Activate
|
||||
callSpecialAPI("./status/clearwarnings").done(self.refresh)
|
||||
// Activate
|
||||
callSpecialAPI("./status/clearwarnings/").done(self.refresh)
|
||||
}
|
||||
|
||||
// Clear messages
|
||||
@@ -637,6 +643,9 @@ $(function() {
|
||||
|
||||
// Shutdown options
|
||||
self.onQueueFinish.subscribe(function(newValue) {
|
||||
// Ignore updates before the page is done
|
||||
if(!self.hasStatusInfo()) return;
|
||||
|
||||
// Something changes
|
||||
callAPI({
|
||||
mode: 'queue',
|
||||
@@ -680,6 +689,14 @@ $(function() {
|
||||
|
||||
// From the upload
|
||||
self.addNZBFromFileForm = function(form) {
|
||||
// Anything?
|
||||
if(!$(form.nzbFile)[0].files[0]) {
|
||||
$('.btn-file').css('border-color', 'red')
|
||||
setTimeout(function() { $('.btn-file').css('border-color', '') }, 2000)
|
||||
return false;
|
||||
}
|
||||
|
||||
// Upload
|
||||
self.addNZBFromFile($(form.nzbFile)[0].files[0]);
|
||||
|
||||
// After that, hide and reset
|
||||
@@ -690,6 +707,13 @@ $(function() {
|
||||
}
|
||||
// From URL
|
||||
self.addNZBFromURL = function(form) {
|
||||
// Anything?
|
||||
if(!$(form.nzbURL).val()) {
|
||||
$(form.nzbURL).css('border-color', 'red')
|
||||
setTimeout(function() { $(form.nzbURL).css('border-color', '') }, 2000)
|
||||
return false;
|
||||
}
|
||||
|
||||
// Add
|
||||
callAPI({
|
||||
mode: "addurl",
|
||||
@@ -737,6 +761,9 @@ $(function() {
|
||||
|
||||
// Load status info
|
||||
self.loadStatusInfo = function(item, event) {
|
||||
// Hide tooltips (otherwise they stay forever..)
|
||||
$('#options-status [data-tooltip="true"]').tooltip('hide')
|
||||
|
||||
// Reset
|
||||
self.hasStatusInfo(false)
|
||||
|
||||
@@ -758,7 +785,7 @@ $(function() {
|
||||
// Only now we can subscribe to the log-level-changes!
|
||||
self.statusInfo.status.loglevel.subscribe(function(newValue) {
|
||||
// Update log-level
|
||||
callSpecialAPI('./status/change_loglevel', {
|
||||
callSpecialAPI('./status/change_loglevel/', {
|
||||
loglevel: newValue
|
||||
});
|
||||
})
|
||||
@@ -778,14 +805,14 @@ $(function() {
|
||||
// Hide before running the test
|
||||
self.hasStatusInfo(false)
|
||||
// Run it and then display it
|
||||
callSpecialAPI('./status/dashrefresh').then(function() {
|
||||
callSpecialAPI('./status/dashrefresh/').then(function() {
|
||||
self.loadStatusInfo(true, true)
|
||||
})
|
||||
}
|
||||
|
||||
// Unblock server
|
||||
self.unblockServer = function(servername) {
|
||||
callSpecialAPI("./status/unblock_server", {
|
||||
callSpecialAPI("./status/unblock_server/", {
|
||||
server: servername
|
||||
}).then(function() {
|
||||
$("#modal-options").modal("hide");
|
||||
@@ -812,7 +839,7 @@ $(function() {
|
||||
self.removeAllOrphaned = function() {
|
||||
if(!self.confirmDeleteHistory() || confirm(glitterTranslate.clearWarn)) {
|
||||
// Delete them all
|
||||
callSpecialAPI("./status/delete_all").then(self.loadStatusInfo)
|
||||
callSpecialAPI("./status/delete_all/").then(self.loadStatusInfo)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -827,7 +854,7 @@ $(function() {
|
||||
self.restartSAB = function() {
|
||||
if(!confirm(glitterTranslate.restart)) return;
|
||||
// Call restart function
|
||||
callSpecialAPI("./config/restart")
|
||||
callSpecialAPI("./config/restart/")
|
||||
|
||||
// Set counter, we need at least 15 seconds
|
||||
self.isRestarting(Math.max(1, Math.floor(15 / self.refreshRate())));
|
||||
@@ -844,13 +871,13 @@ $(function() {
|
||||
// Repair queue
|
||||
self.repairQueue = function() {
|
||||
if(!confirm(glitterTranslate.repair)) return;
|
||||
callSpecialAPI("./config/repair").then(function() {
|
||||
callSpecialAPI("./config/repair/").then(function() {
|
||||
$("#modal-options").modal("hide");
|
||||
})
|
||||
}
|
||||
// Force disconnect
|
||||
self.forceDisconnect = function() {
|
||||
callSpecialAPI("./status/disconnect").then(function() {
|
||||
callSpecialAPI("./status/disconnect/").then(function() {
|
||||
$("#modal-options").modal("hide");
|
||||
})
|
||||
}
|
||||
@@ -886,7 +913,7 @@ $(function() {
|
||||
if(newRelease) {
|
||||
self.allMessages.push({
|
||||
index: 'UpdateMsg',
|
||||
type: 'INFO',
|
||||
type: glitterTranslate.status['INFO'],
|
||||
text: ('<a class="queue-update-sab" href="'+newReleaseUrl+'" target="_blank">'+glitterTranslate.updateAvailable+' '+newRelease+' <span class="glyphicon glyphicon-save"></span></a>'),
|
||||
css: 'info'
|
||||
});
|
||||
@@ -896,7 +923,7 @@ $(function() {
|
||||
if(!response.config.misc.cache_limit && localStorageGetItem('CacheMsg')*1+(1000*3600*24*5) < Date.now()) {
|
||||
self.allMessages.push({
|
||||
index: 'CacheMsg',
|
||||
type: 'INFO',
|
||||
type: glitterTranslate.status['INFO'],
|
||||
text: ('<a href="./config/general/#cache_limit">'+glitterTranslate.useCache.replace(/<br \/>/g, " ")+' <span class="glyphicon glyphicon-cog"></span></a>'),
|
||||
css: 'info',
|
||||
clear: function() { self.clearMessages('CacheMsg')}
|
||||
@@ -908,7 +935,7 @@ $(function() {
|
||||
var orphanMsg = localStorageGetItem('OrphanedMsg')*1+(1000*3600*24*5) < Date.now();
|
||||
// Delay the check
|
||||
if(orphanMsg) {
|
||||
setTimeout(self.loadStatusInfo, 2000);
|
||||
setTimeout(self.loadStatusInfo, 200);
|
||||
}
|
||||
|
||||
// On any status load we check Orphaned folders
|
||||
@@ -922,8 +949,8 @@ $(function() {
|
||||
if(!ko.utils.arrayFirst(self.allMessages(), function(item) { return item.index == 'OrphanedMsg' })) {
|
||||
self.allMessages.push({
|
||||
index: 'OrphanedMsg',
|
||||
type: 'INFO',
|
||||
text: glitterTranslate.orphanedJobsMsg + ' <a href="#" onclick="$(\'a[href=#modal-options]\').click().parent().click(); $(\'a[href=#options-orphans]\').click()"><span class="glyphicon glyphicon-wrench"></span></a>',
|
||||
type: glitterTranslate.status['INFO'],
|
||||
text: glitterTranslate.orphanedJobsMsg + ' <a href="#" onclick="showOrphans()"><span class="glyphicon glyphicon-wrench"></span></a>',
|
||||
css: 'info',
|
||||
clear: function() { self.clearMessages('OrphanedMsg')}
|
||||
});
|
||||
@@ -936,6 +963,17 @@ $(function() {
|
||||
}
|
||||
})
|
||||
|
||||
// Message about localStorage not being enabled every 20 days
|
||||
if(!hasLocalStorage && localStorageGetItem('LocalStorageMsg')*1+(1000*3600*24*20) < Date.now()) {
|
||||
self.allMessages.push({
|
||||
index: 'LocalStorageMsg',
|
||||
type: glitterTranslate.status['WARNING'].replace(':', ''),
|
||||
text: glitterTranslate.noLocalStorage,
|
||||
css: 'warning',
|
||||
clear: function() { self.clearMessages('LocalStorageMsg')}
|
||||
});
|
||||
}
|
||||
|
||||
/***
|
||||
Date-stuff
|
||||
***/
|
||||
@@ -1562,6 +1600,9 @@ $(function() {
|
||||
|
||||
// Edit name
|
||||
self.editName = function(data, event) {
|
||||
// Not when still grabbing
|
||||
if(self.isGrabbing()) return false;
|
||||
|
||||
// is there a password in there?
|
||||
var extractOutput = extractTitleAndPassword(self.name())
|
||||
|
||||
@@ -1606,6 +1647,8 @@ $(function() {
|
||||
|
||||
// See items
|
||||
self.showFiles = function() {
|
||||
// Not when still grabbing
|
||||
if(self.isGrabbing()) return false;
|
||||
// Trigger update
|
||||
parent.parent.filelist.loadFiles(self)
|
||||
}
|
||||
@@ -2277,7 +2320,7 @@ $(function() {
|
||||
dataToSend['action_size'] = Math.abs(nrMoves);
|
||||
|
||||
// Activate with this weird URL "API"
|
||||
callSpecialAPI("./nzb/" + self.currentItem.id + "/bulk_operation", dataToSend)
|
||||
callSpecialAPI("./nzb/" + self.currentItem.id + "/bulk_operation/", dataToSend)
|
||||
};
|
||||
|
||||
// Remove selected files
|
||||
@@ -2294,7 +2337,7 @@ $(function() {
|
||||
})
|
||||
|
||||
// Activate with this weird URL "API"
|
||||
callSpecialAPI("./nzb/" + self.currentItem.id + "/bulk_operation", dataToSend).then(function() {
|
||||
callSpecialAPI("./nzb/" + self.currentItem.id + "/bulk_operation/", dataToSend).then(function() {
|
||||
// Fade it out
|
||||
$('.item-files-table input:checked:not(:disabled)').parents('tr').fadeOut(fadeOnDeleteDuration, function() {
|
||||
// Set state of the check-all
|
||||
@@ -2306,7 +2349,7 @@ $(function() {
|
||||
// For changing the passwords
|
||||
self.setNzbPassword = function() {
|
||||
// Activate with this weird URL "API"
|
||||
callSpecialAPI("./nzb/" + self.currentItem.id + "/save", {
|
||||
callSpecialAPI("./nzb/" + self.currentItem.id + "/save/", {
|
||||
name: self.modalTitle(),
|
||||
password: $('#nzb_password').val()
|
||||
}).then(function() {
|
||||
@@ -2629,12 +2672,18 @@ function keepOpen(thisItem) {
|
||||
|
||||
// Show history details
|
||||
function showDetails(thisItem) {
|
||||
// Open the details of this
|
||||
// Needs timeout, otherwise it thinks its the 'close' click
|
||||
setTimeout(function() {
|
||||
// Unfortunatly the .dropdown('toggle') doesn't work in this setup, so work-a-round
|
||||
|
||||
// Open the details of this, or close it?
|
||||
if($(thisItem).parent().find('.delete>.dropdown').hasClass('open')) {
|
||||
// One click = close
|
||||
$(thisItem).parent().find('.delete>.dropdown>a').click()
|
||||
},1)
|
||||
|
||||
} else {
|
||||
// Needs timeout, otherwise it thinks its the 'close' click for some reason
|
||||
setTimeout(function() {
|
||||
$(thisItem).parent().find('.delete>.dropdown>a').click()
|
||||
},1)
|
||||
}
|
||||
}
|
||||
|
||||
// Check all functionality
|
||||
@@ -2701,3 +2750,9 @@ function hideCompletedFiles() {
|
||||
localStorageSetItem('showCompletedFiles', 'Yes')
|
||||
}
|
||||
}
|
||||
|
||||
// Show status modal and switch to orphaned jobs tab
|
||||
function showOrphans() {
|
||||
$('a[href="#modal-options"]').click().parent().click();
|
||||
$('a[href="#options-orphans"]').click()
|
||||
}
|
||||
@@ -810,7 +810,7 @@ tr.queue-item>td:first-child>a {
|
||||
}
|
||||
|
||||
.table-messages .queue-message-text {
|
||||
word-break: break-all;
|
||||
word-wrap: break-word;
|
||||
}
|
||||
|
||||
.table-messages .queue-update-sab {
|
||||
@@ -915,7 +915,7 @@ tr.queue-item>td:first-child>a {
|
||||
}
|
||||
|
||||
.history-status-table .col-sm-10 {
|
||||
word-break: break-word;
|
||||
word-wrap: break-word;
|
||||
}
|
||||
|
||||
.history-status-table a {
|
||||
@@ -1235,9 +1235,11 @@ tr.queue-item>td:first-child>a {
|
||||
}
|
||||
|
||||
#modal-options .options-server-box .btn {
|
||||
position: absolute;
|
||||
right: 10px;
|
||||
z-index:2000;
|
||||
float: right;
|
||||
}
|
||||
|
||||
#modal-options .options-server-box .alert {
|
||||
margin-bottom: 5px;
|
||||
}
|
||||
|
||||
#modal-options .options-server-box:last-child {
|
||||
@@ -1403,6 +1405,11 @@ tr.queue-item>td:first-child>a {
|
||||
max-width: 100px;
|
||||
}
|
||||
|
||||
.btn-file,
|
||||
input[name="nzbURL"] {
|
||||
transition : border 500ms ease-out;
|
||||
}
|
||||
|
||||
/* HELP MODAL */
|
||||
|
||||
#modal-help {
|
||||
|
||||
@@ -49,6 +49,8 @@
|
||||
"localipv4": "$localipv4",
|
||||
"publicipv4": "$publicipv4",
|
||||
"ipv6": "$ipv6",
|
||||
"pystone": "$pystone",
|
||||
"cpumodel": "$cpumodel",
|
||||
"dnslookup": "$dnslookup",
|
||||
<!--#set $downloaddir = $downloaddir.replace('\\','\\\\')#-->
|
||||
"downloaddir": "$downloaddir",
|
||||
|
||||
@@ -134,7 +134,7 @@
|
||||
<tr class="<!--#if $odd then "odd" else "even"#-->">
|
||||
<td>$T('dashboard-localIP4')</td>
|
||||
<td>
|
||||
<!--#if $publicipv4#-->
|
||||
<!--#if $localipv4#-->
|
||||
$localipv4
|
||||
<!--#else#-->
|
||||
<strong style="color: red;">$T('dashboard-connectionError')</strong>
|
||||
|
||||
@@ -12,11 +12,16 @@
|
||||
|
||||
[Unit]
|
||||
Description=SABnzbd binary newsreader
|
||||
Wants=network-online.target
|
||||
After=network-online.target
|
||||
|
||||
[Service]
|
||||
ExecStart=/opt/sabnzbd/SABnzbd.py --logging 1 --browser 0
|
||||
User=%I
|
||||
Group=%I
|
||||
Type = simple
|
||||
Restart = on-failure
|
||||
|
||||
|
||||
[Install]
|
||||
WantedBy=multi-user.target
|
||||
|
||||
1866
po/main/da.po
1866
po/main/da.po
File diff suppressed because it is too large
Load Diff
1868
po/main/de.po
1868
po/main/de.po
File diff suppressed because it is too large
Load Diff
@@ -108,3 +108,6 @@ msgstr "How long or until when do you want to pause? (in English!)"
|
||||
msgid "Timeleft"
|
||||
msgstr "Time left"
|
||||
|
||||
#: sabnzbd/skintext.py:791 # sabnzbd/skintext.py:871
|
||||
msgid "Optionally specify a filename"
|
||||
msgstr "Optionally specify a name"
|
||||
|
||||
1866
po/main/es.po
1866
po/main/es.po
File diff suppressed because it is too large
Load Diff
1866
po/main/fi.po
1866
po/main/fi.po
File diff suppressed because it is too large
Load Diff
2651
po/main/fr.po
2651
po/main/fr.po
File diff suppressed because it is too large
Load Diff
1866
po/main/nb.po
1866
po/main/nb.po
File diff suppressed because it is too large
Load Diff
1877
po/main/nl.po
1877
po/main/nl.po
File diff suppressed because it is too large
Load Diff
1866
po/main/pl.po
1866
po/main/pl.po
File diff suppressed because it is too large
Load Diff
1866
po/main/pt_BR.po
1866
po/main/pt_BR.po
File diff suppressed because it is too large
Load Diff
1866
po/main/ro.po
1866
po/main/ro.po
File diff suppressed because it is too large
Load Diff
1866
po/main/ru.po
1866
po/main/ru.po
File diff suppressed because it is too large
Load Diff
1866
po/main/sr.po
1866
po/main/sr.po
File diff suppressed because it is too large
Load Diff
1872
po/main/sv.po
1872
po/main/sv.po
File diff suppressed because it is too large
Load Diff
1874
po/main/zh_CN.po
1874
po/main/zh_CN.po
File diff suppressed because it is too large
Load Diff
1
portable.cmd
Normal file
1
portable.cmd
Normal file
@@ -0,0 +1 @@
|
||||
@%~dp0SABnzbd.exe -f %~dp0 %1 %2 %3 %4 %5 %6 %7 %8 %9
|
||||
@@ -197,9 +197,12 @@ def sig_handler(signum=None, frame=None):
|
||||
INIT_LOCK = Lock()
|
||||
|
||||
|
||||
def connect_db(thread_index):
|
||||
def connect_db(thread_index=0):
|
||||
# Create a connection and store it in the current thread
|
||||
cherrypy.thread_data.history_db = sabnzbd.database.get_history_handle()
|
||||
if not (hasattr(cherrypy.thread_data, 'history_db') and cherrypy.thread_data.history_db):
|
||||
cherrypy.thread_data.history_db = sabnzbd.database.get_history_handle()
|
||||
return cherrypy.thread_data.history_db
|
||||
|
||||
|
||||
|
||||
@synchronized(INIT_LOCK)
|
||||
@@ -271,8 +274,9 @@ def initialize(pause_downloader=False, clean_up=False, evalSched=False, repair=0
|
||||
sabnzbd.encoding.change_fsys(cfg.fsys_type())
|
||||
|
||||
# Set cache limit
|
||||
if (sabnzbd.WIN32 or sabnzbd.DARWIN) and not cfg.cache_limit():
|
||||
cfg.cache_limit.set('200M')
|
||||
if sabnzbd.WIN32 or sabnzbd.DARWIN:
|
||||
if cfg.cache_limit() == '' or cfg.cache_limit() == '200M':
|
||||
cfg.cache_limit.set('450M')
|
||||
ArticleCache.do.new_limit(cfg.cache_limit.get_int())
|
||||
|
||||
check_incomplete_vs_complete()
|
||||
@@ -285,9 +289,7 @@ def initialize(pause_downloader=False, clean_up=False, evalSched=False, repair=0
|
||||
lang.set_language(cfg.language())
|
||||
sabnzbd.api.clear_trans_cache()
|
||||
|
||||
# Check for old queue (when a new queue is not present)
|
||||
if not os.path.exists(os.path.join(cfg.admin_dir.get_path(), QUEUE_FILE_NAME)):
|
||||
OLD_QUEUE = bool(misc.globber(cfg.admin_dir.get_path(), QUEUE_FILE_TMPL % '?'))
|
||||
OLD_QUEUE = check_old_queue()
|
||||
|
||||
sabnzbd.change_queue_complete_action(cfg.queue_complete(), new=False)
|
||||
|
||||
@@ -486,18 +488,24 @@ def guard_fsys_type():
|
||||
""" Callback for change of file system naming type """
|
||||
sabnzbd.encoding.change_fsys(cfg.fsys_type())
|
||||
|
||||
|
||||
def guard_https_ver():
|
||||
""" Callback for change of https verification """
|
||||
def set_https_verification(value):
|
||||
prev = False
|
||||
try:
|
||||
import ssl
|
||||
if hasattr(ssl, '_create_default_https_context'):
|
||||
if cfg.enable_https_verification():
|
||||
prev = ssl._create_default_https_context == ssl.create_default_context
|
||||
if value:
|
||||
ssl._create_default_https_context = ssl.create_default_context
|
||||
else:
|
||||
ssl._create_default_https_context = ssl._create_unverified_context
|
||||
except ImportError:
|
||||
pass
|
||||
return prev
|
||||
|
||||
|
||||
def guard_https_ver():
|
||||
""" Callback for change of https verification """
|
||||
set_https_verification(cfg.enable_https_verification())
|
||||
|
||||
|
||||
def add_url(url, pp=None, script=None, cat=None, priority=None, nzbname=None):
|
||||
@@ -923,8 +931,7 @@ def remove_data(_id, path):
|
||||
os.remove(path)
|
||||
logging.info("%s removed", path)
|
||||
except:
|
||||
logging.info("Failed to remove %s", path)
|
||||
logging.info("Traceback: ", exc_info=True)
|
||||
logging.debug("Failed to remove %s", path)
|
||||
|
||||
|
||||
@synchronized(IO_LOCK)
|
||||
@@ -952,7 +959,7 @@ def save_admin(data, _id, do_pickle=True):
|
||||
|
||||
|
||||
@synchronized(IO_LOCK)
|
||||
def load_admin(_id, remove=False, do_pickle=True):
|
||||
def load_admin(_id, remove=False, do_pickle=True, silent=False):
|
||||
""" Read data in admin folder in specified format """
|
||||
path = os.path.join(cfg.admin_dir.get_path(), _id)
|
||||
logging.info("Loading data for %s from %s", _id, path)
|
||||
@@ -972,9 +979,10 @@ def load_admin(_id, remove=False, do_pickle=True):
|
||||
if remove:
|
||||
os.remove(path)
|
||||
except:
|
||||
excepterror = str(sys.exc_info()[0])
|
||||
logging.error(T('Loading %s failed with error %s'), path, excepterror)
|
||||
logging.info("Traceback: ", exc_info=True)
|
||||
if not silent:
|
||||
excepterror = str(sys.exc_info()[0])
|
||||
logging.error(T('Loading %s failed with error %s'), path, excepterror)
|
||||
logging.info("Traceback: ", exc_info=True)
|
||||
return None
|
||||
|
||||
return data
|
||||
@@ -1121,6 +1129,24 @@ def wait_for_download_folder():
|
||||
logging.debug('Waiting for "incomplete" folder')
|
||||
time.sleep(2.0)
|
||||
|
||||
def check_old_queue():
|
||||
""" Check for old queue (when a new queue is not present) """
|
||||
old = False
|
||||
if not os.path.exists(os.path.join(cfg.admin_dir.get_path(), QUEUE_FILE_NAME)):
|
||||
for ver in (QUEUE_VERSION -1 , QUEUE_VERSION - 2, QUEUE_VERSION - 3):
|
||||
data = load_admin(QUEUE_FILE_TMPL % str(ver))
|
||||
if data:
|
||||
break
|
||||
try:
|
||||
old = bool(data and isinstance(data, tuple) and len(data[1]))
|
||||
except (TypeError, IndexError):
|
||||
pass
|
||||
if old and sabnzbd.WIN32 and ver < 10 and sabnzbd.DIR_LCLDATA != sabnzbd.DIR_HOME \
|
||||
and misc.is_relative_path(cfg.download_dir()):
|
||||
# For Windows and when version < 10: adjust old default location
|
||||
cfg.download_dir.set('Documents/' + cfg.download_dir())
|
||||
return old
|
||||
|
||||
|
||||
# Required wrapper because nzbstuff.py cannot import downloader.py
|
||||
def highest_server(me):
|
||||
@@ -1133,11 +1159,11 @@ def proxy_pre_queue(name, pp, cat, script, priority, size, groups):
|
||||
|
||||
def test_ipv6():
|
||||
""" Check if external IPv6 addresses are reachable """
|
||||
if not cfg.ipv6_test_host():
|
||||
if not cfg.selftest_host():
|
||||
# User disabled the test, assume active IPv6
|
||||
return True
|
||||
try:
|
||||
info = socket.getaddrinfo(cfg.ipv6_test_host(), 80, socket.AF_INET6, socket.SOCK_STREAM, socket.IPPROTO_IP, socket.AI_CANONNAME)
|
||||
info = socket.getaddrinfo(cfg.selftest_host(), 443, socket.AF_INET6, socket.SOCK_STREAM, socket.IPPROTO_IP, socket.AI_CANONNAME)
|
||||
except:
|
||||
logging.debug("Test IPv6: Disabling IPv6, because it looks like it's not available. Reason: %s", sys.exc_info()[0] )
|
||||
return False
|
||||
|
||||
@@ -482,7 +482,7 @@ def _api_history(name, output, kwargs):
|
||||
special = value.lower()
|
||||
del_files = bool(int_conv(kwargs.get('del_files')))
|
||||
if special in ('all', 'failed', 'completed'):
|
||||
history_db = cherrypy.thread_data.history_db
|
||||
history_db = sabnzbd.connect_db()
|
||||
if special in ('all', 'failed'):
|
||||
if del_files:
|
||||
del_job_files(history_db.get_failed_paths(search))
|
||||
@@ -1238,13 +1238,15 @@ def build_queue(web_dir=None, root=None, verbose=False, prim=True, webdir='', ve
|
||||
slot['mbdone_fmt'] = locale.format('%d', int(mb - mbleft), True)
|
||||
slot['size'] = format_bytes(bytes)
|
||||
slot['sizeleft'] = format_bytes(bytesleft)
|
||||
if not Downloader.do.paused and status not in (Status.PAUSED, Status.FETCHING) and not found_active:
|
||||
if not Downloader.do.paused and status not in (Status.PAUSED, Status.FETCHING, Status.GRABBING) and not found_active:
|
||||
if status == Status.CHECKING:
|
||||
slot['status'] = Status.CHECKING
|
||||
else:
|
||||
slot['status'] = Status.DOWNLOADING
|
||||
found_active = True
|
||||
else:
|
||||
# ensure compatibility of API status
|
||||
if status in (Status.DELETED, ): status = Status.DOWNLOADING
|
||||
slot['status'] = "%s" % (status)
|
||||
if priority == TOP_PRIORITY:
|
||||
slot['priority'] = 'Force'
|
||||
@@ -1574,7 +1576,7 @@ def options_list(output):
|
||||
def retry_job(job, new_nzb, password):
|
||||
""" Re enter failed job in the download queue """
|
||||
if job:
|
||||
history_db = cherrypy.thread_data.history_db
|
||||
history_db = sabnzbd.connect_db()
|
||||
futuretype, url, pp, script, cat = history_db.get_other(job)
|
||||
if futuretype:
|
||||
sabnzbd.add_url(url, pp, script, cat)
|
||||
@@ -1590,7 +1592,7 @@ def retry_job(job, new_nzb, password):
|
||||
|
||||
def retry_all_jobs():
|
||||
""" Re enter all failed jobs in the download queue """
|
||||
history_db = cherrypy.thread_data.history_db
|
||||
history_db = sabnzbd.connect_db()
|
||||
return NzbQueue.do.retry_all_jobs(history_db)
|
||||
|
||||
|
||||
@@ -1608,7 +1610,7 @@ def del_hist_job(job, del_files):
|
||||
if path:
|
||||
PostProcessor.do.delete(job, del_files=del_files)
|
||||
else:
|
||||
history_db = cherrypy.thread_data.history_db
|
||||
history_db = sabnzbd.connect_db()
|
||||
path = history_db.get_path(job)
|
||||
PostProcessor.do.delete(job, del_files=del_files)
|
||||
history_db.remove_history(job)
|
||||
@@ -1815,7 +1817,7 @@ def build_history(start=None, limit=None, verbose=False, verbose_list=None, sear
|
||||
|
||||
# Aquire the db instance
|
||||
try:
|
||||
history_db = cherrypy.thread_data.history_db
|
||||
history_db = sabnzbd.connect_db()
|
||||
close_db = False
|
||||
except:
|
||||
# Required for repairs at startup because Cherrypy isn't active yet
|
||||
|
||||
@@ -24,7 +24,7 @@ import threading
|
||||
|
||||
import sabnzbd
|
||||
from sabnzbd.decorators import synchronized
|
||||
from sabnzbd.constants import GIGI
|
||||
from sabnzbd.constants import GIGI, Status
|
||||
|
||||
|
||||
ARTICLE_LOCK = threading.Lock()
|
||||
@@ -60,12 +60,12 @@ class ArticleCache(object):
|
||||
nzf = article.nzf
|
||||
nzo = nzf.nzo
|
||||
|
||||
if nzf.deleted or nzo.deleted:
|
||||
if nzo.status in (Status.COMPLETED, Status.DELETED):
|
||||
# Do not discard this article because the
|
||||
# file might still be processed at this moment!!
|
||||
if sabnzbd.LOG_ALL:
|
||||
logging.debug("%s would be discarded", article)
|
||||
# return
|
||||
logging.debug("%s is discarded", article)
|
||||
return
|
||||
|
||||
saved_articles = article.nzf.nzo.saved_articles
|
||||
|
||||
@@ -142,12 +142,12 @@ class ArticleCache(object):
|
||||
nzf = article.nzf
|
||||
nzo = nzf.nzo
|
||||
|
||||
if nzf.deleted or nzo.deleted:
|
||||
if nzo.status in (Status.COMPLETED, Status.DELETED):
|
||||
# Do not discard this article because the
|
||||
# file might still be processed at this moment!!
|
||||
if sabnzbd.LOG_ALL:
|
||||
logging.debug("%s would be discarded", article)
|
||||
# return
|
||||
logging.debug("%s is discarded", article)
|
||||
return
|
||||
|
||||
art_id = article.get_art_id()
|
||||
if art_id:
|
||||
|
||||
@@ -199,7 +199,7 @@ class BPSMeter(object):
|
||||
self.defaults()
|
||||
# Force update of counters and validate data
|
||||
try:
|
||||
for server in self.grand_total:
|
||||
for server in self.grand_total.keys():
|
||||
self.update(server)
|
||||
except TypeError:
|
||||
self.defaults()
|
||||
@@ -446,7 +446,7 @@ class BPSMeter(object):
|
||||
|
||||
def midnight(self):
|
||||
""" Midnight action: dummy update for all servers """
|
||||
for server in self.day_total:
|
||||
for server in self.day_total.keys():
|
||||
self.update(server)
|
||||
|
||||
|
||||
|
||||
@@ -82,8 +82,8 @@ replace_illegal = OptionBool('misc', 'replace_illegal', True)
|
||||
pre_script = OptionStr('misc', 'pre_script', 'None')
|
||||
script_can_fail = OptionBool('misc', 'script_can_fail', False)
|
||||
start_paused = OptionBool('misc', 'start_paused', False)
|
||||
enable_https_verification = OptionBool('misc', 'enable_https_verification', True)
|
||||
ipv6_test_host = OptionStr('misc', 'ipv6_test_host', 'test-ipv6.sabnzbd.org')
|
||||
enable_https_verification = OptionBool('misc', 'enable_https_verification', False)
|
||||
selftest_host = OptionStr('misc', 'selftest_host', 'self-test.sabnzbd.org')
|
||||
|
||||
enable_unrar = OptionBool('misc', 'enable_unrar', True)
|
||||
enable_unzip = OptionBool('misc', 'enable_unzip', True)
|
||||
@@ -142,7 +142,7 @@ no_dupes = OptionNumber('misc', 'no_dupes', 0)
|
||||
no_series_dupes = OptionNumber('misc', 'no_series_dupes', 0)
|
||||
backup_for_duplicates = OptionBool('misc', 'backup_for_duplicates', True)
|
||||
|
||||
ignore_samples = OptionNumber('misc', 'ignore_samples', 0, 0, 2)
|
||||
ignore_samples = OptionBool('misc', 'ignore_samples', False)
|
||||
create_group_folders = OptionBool('misc', 'create_group_folders', False)
|
||||
auto_sort = OptionBool('misc', 'auto_sort', False)
|
||||
folder_rename = OptionBool('misc', 'folder_rename', True)
|
||||
@@ -257,7 +257,7 @@ inet_exposure = OptionNumber('misc', 'inet_exposure', 0, protect=True) # 0=loca
|
||||
max_art_tries = OptionNumber('misc', 'max_art_tries', 3, 2)
|
||||
max_art_opt = OptionBool('misc', 'max_art_opt', False)
|
||||
use_pickle = OptionBool('misc', 'use_pickle', False)
|
||||
no_ipv6 = OptionBool('misc', 'no_ipv6', False)
|
||||
ipv6_hosting = OptionBool('misc', 'ipv6_hosting', False)
|
||||
|
||||
# [ncenter]
|
||||
ncenter_enable = OptionBool('ncenter', 'ncenter_enable', sabnzbd.DARWIN_VERSION > 7)
|
||||
@@ -332,16 +332,16 @@ pushover_token = OptionStr('pushover', 'pushover_token')
|
||||
pushover_userkey = OptionStr('pushover', 'pushover_userkey')
|
||||
pushover_device = OptionStr('pushover', 'pushover_device')
|
||||
pushover_enable = OptionBool('pushover', 'pushover_enable')
|
||||
pushover_prio_startup = OptionNumber('pushover', 'pushover_prio_startup', -2)
|
||||
pushover_prio_startup = OptionNumber('pushover', 'pushover_prio_startup', -3)
|
||||
pushover_prio_download = OptionNumber('pushover', 'pushover_prio_download', -2)
|
||||
pushover_prio_pp = OptionNumber('pushover', 'pushover_prio_pp', -2)
|
||||
pushover_prio_complete = OptionNumber('pushover', 'pushover_prio_complete', 1)
|
||||
pushover_prio_failed = OptionNumber('pushover', 'pushover_prio_failed', 1)
|
||||
pushover_prio_pp = OptionNumber('pushover', 'pushover_prio_pp', -3)
|
||||
pushover_prio_complete = OptionNumber('pushover', 'pushover_prio_complete', -1)
|
||||
pushover_prio_failed = OptionNumber('pushover', 'pushover_prio_failed', -1)
|
||||
pushover_prio_disk_full = OptionNumber('pushover', 'pushover_prio_disk_full', 1)
|
||||
pushover_prio_warning = OptionNumber('pushover', 'pushover_prio_warning', -2)
|
||||
pushover_prio_error = OptionNumber('pushover', 'pushover_prio_error', -2)
|
||||
pushover_prio_warning = OptionNumber('pushover', 'pushover_prio_warning', 1)
|
||||
pushover_prio_error = OptionNumber('pushover', 'pushover_prio_error', 1)
|
||||
pushover_prio_queue_done = OptionNumber('pushover', 'pushover_prio_queue_done', -1)
|
||||
pushover_prio_other = OptionNumber('pushover', 'pushover_prio_other', -2)
|
||||
pushover_prio_other = OptionNumber('pushover', 'pushover_prio_other', -3)
|
||||
|
||||
# [pushbullet]
|
||||
pushbullet_enable = OptionBool('pushbullet', 'pushbullet_enable')
|
||||
|
||||
@@ -300,7 +300,7 @@ class OptionStr(Option):
|
||||
def set(self, value):
|
||||
""" Set stripped value """
|
||||
error = None
|
||||
if type(value) == type('') and self.__strip:
|
||||
if isinstance(value, basestring) and self.__strip:
|
||||
value = value.strip()
|
||||
if self.__validation:
|
||||
error, val = self.__validation(value)
|
||||
|
||||
@@ -109,7 +109,7 @@ DEF_QRATE = 0
|
||||
MIN_DECODE_QUEUE = 5
|
||||
MAX_DECODE_QUEUE = 10
|
||||
MAX_WARNINGS = 20
|
||||
MAX_WIN_DFOLDER = 40
|
||||
MAX_WIN_DFOLDER = 60
|
||||
|
||||
REPAIR_PRIORITY = 3
|
||||
TOP_PRIORITY = 2
|
||||
@@ -150,19 +150,20 @@ sample_match = r'((^|[\W_])sample\d*[\W_])' # something-sample.avi
|
||||
|
||||
|
||||
class Status():
|
||||
COMPLETED = 'Completed'
|
||||
CHECKING = 'Checking'
|
||||
DOWNLOADING = 'Downloading'
|
||||
EXTRACTING = 'Extracting'
|
||||
FAILED = 'Failed'
|
||||
FETCHING = 'Fetching'
|
||||
GRABBING = 'Grabbing'
|
||||
MOVING = 'Moving'
|
||||
PAUSED = 'Paused'
|
||||
QUEUED = 'Queued'
|
||||
QUICK_CHECK = 'QuickCheck'
|
||||
REPAIRING = 'Repairing'
|
||||
RUNNING = 'Running'
|
||||
VERIFYING = 'Verifying'
|
||||
COMPLETED = 'Completed' # PP: Job is finished
|
||||
CHECKING = 'Checking' # Q: Pre-check is running
|
||||
DOWNLOADING = 'Downloading' # Q: Normal downloading
|
||||
EXTRACTING = 'Extracting' # PP: Archives are being extraced
|
||||
FAILED = 'Failed' # PP: Job has failed, now in History
|
||||
FETCHING = 'Fetching' # Q: Job is downloading extra par2 files
|
||||
GRABBING = 'Grabbing' # Q: Getting an NZB from an external site
|
||||
MOVING = 'Moving' # PP: Files are being moved
|
||||
PAUSED = 'Paused' # Q: Job is paused
|
||||
QUEUED = 'Queued' # Q: Job is waiting for its turn to download
|
||||
QUICK_CHECK = 'QuickCheck' # PP: QuickCheck verification is running
|
||||
REPAIRING = 'Repairing' # PP: Job is being repaired (by par2)
|
||||
RUNNING = 'Running' # PP: User's post processing script is running
|
||||
VERIFYING = 'Verifying' # PP: Job is being verified (by par2)
|
||||
DELETED = 'Deleted' # Q: Job has been deleted (and is almost gone)
|
||||
|
||||
NOTIFY_KEYS = ('startup', 'download', 'pp', 'complete', 'failed', 'queue_done', 'disk_full', 'warning', 'error', 'other')
|
||||
|
||||
@@ -237,9 +237,9 @@ class HistoryDB(object):
|
||||
post = ''
|
||||
if categories:
|
||||
categories = ['*' if c == 'Default' else c for c in categories]
|
||||
post = ' AND (CATEGORY = "'
|
||||
post += '" OR CATEGORY = "'.join(categories)
|
||||
post += '" )'
|
||||
post = " AND (CATEGORY = '"
|
||||
post += "' OR CATEGORY = '".join(categories)
|
||||
post += "' )"
|
||||
if failed_only:
|
||||
post += ' AND STATUS = "Failed"'
|
||||
|
||||
@@ -280,7 +280,7 @@ class HistoryDB(object):
|
||||
series = series.lower().replace('.', ' ').replace('_', ' ').replace(' ', ' ')
|
||||
if series and season and episode:
|
||||
pattern = '%s/%s/%s' % (series, season, episode)
|
||||
res = self.execute('select count(*) from History WHERE series = ? AND STATUS != "Failed"', (pattern,))
|
||||
res = self.execute("select count(*) from History WHERE series = ? AND STATUS != 'Failed'", (pattern,))
|
||||
if res:
|
||||
try:
|
||||
total = self.c.fetchone().get('count(*)')
|
||||
@@ -291,7 +291,7 @@ class HistoryDB(object):
|
||||
def have_md5sum(self, md5sum):
|
||||
""" Check whether this md5sum already in History """
|
||||
total = 0
|
||||
res = self.execute('select count(*) from History WHERE md5sum = ? AND STATUS != "Failed"', (md5sum,))
|
||||
res = self.execute("select count(*) from History WHERE md5sum = ? AND STATUS != 'Failed'", (md5sum,))
|
||||
if res:
|
||||
try:
|
||||
total = self.c.fetchone().get('count(*)')
|
||||
@@ -495,7 +495,7 @@ def unpack_history_info(item):
|
||||
item['stage_log'] = [x for x in lst if x is not None]
|
||||
|
||||
if item['script_log']:
|
||||
item['script_log'] = zlib.decompress(item['script_log'][:])
|
||||
item['script_log'] = ''
|
||||
# The action line is only available for items in the postproc queue
|
||||
if not item.has_key('action_line'):
|
||||
item['action_line'] = ''
|
||||
|
||||
@@ -37,7 +37,7 @@ from sabnzbd.constants import MAX_DECODE_QUEUE, MIN_DECODE_QUEUE
|
||||
from sabnzbd.articlecache import ArticleCache
|
||||
import sabnzbd.downloader
|
||||
import sabnzbd.cfg as cfg
|
||||
from sabnzbd.encoding import name_fixer
|
||||
from sabnzbd.encoding import yenc_name_fixer
|
||||
from sabnzbd.misc import match_str
|
||||
|
||||
|
||||
@@ -245,7 +245,7 @@ def decode(article, data):
|
||||
try:
|
||||
for i in xrange(min(40, len(data))):
|
||||
if data[i].startswith('begin '):
|
||||
nzf.filename = name_fixer(data[i].split(None, 2)[2])
|
||||
nzf.filename = yenc_name_fixer(data[i].split(None, 2)[2])
|
||||
nzf.type = 'uu'
|
||||
found = True
|
||||
break
|
||||
@@ -267,7 +267,7 @@ def decode(article, data):
|
||||
# Deal with yenc encoded posts
|
||||
elif (ybegin and yend):
|
||||
if 'name' in ybegin:
|
||||
nzf.filename = name_fixer(ybegin['name'])
|
||||
nzf.filename = yenc_name_fixer(ybegin['name'])
|
||||
else:
|
||||
logging.debug("Possible corrupt header detected => ybegin: %s", ybegin)
|
||||
nzf.type = 'yenc'
|
||||
|
||||
@@ -62,11 +62,6 @@ class Server(object):
|
||||
def __init__(self, id, displayname, host, port, timeout, threads, priority, ssl, ssl_type, send_group, username=None,
|
||||
password=None, optional=False, retention=0, categories=None):
|
||||
|
||||
# If no ssl is protocol set, used highest available one
|
||||
protocols = ssl_protocols()
|
||||
if ssl and protocols and ssl_type not in protocols:
|
||||
ssl_type = protocols[0]
|
||||
|
||||
self.id = id
|
||||
self.newid = None
|
||||
self.restart = False
|
||||
@@ -77,7 +72,7 @@ class Server(object):
|
||||
self.threads = threads
|
||||
self.priority = priority
|
||||
self.ssl = ssl
|
||||
self.ssl_type = ssl_type
|
||||
self.ssl_type = None
|
||||
self.optional = optional
|
||||
self.retention = retention
|
||||
self.send_group = send_group
|
||||
@@ -98,6 +93,11 @@ class Server(object):
|
||||
self.have_body = 'free.xsusenet.com' not in host
|
||||
self.have_stat = True # Assume server has "STAT", until proven otherwise
|
||||
|
||||
if ssl:
|
||||
# When the user has set a supported protocol, use it
|
||||
if ssl_type and ssl_type in ssl_protocols():
|
||||
self.ssl_type = ssl_type
|
||||
|
||||
for i in range(threads):
|
||||
self.idle_threads.append(NewsWrapper(self, i + 1))
|
||||
|
||||
@@ -239,8 +239,9 @@ class Downloader(Thread):
|
||||
@synchronized_CV
|
||||
def resume(self):
|
||||
logging.info("Resuming")
|
||||
if self.paused:
|
||||
growler.send_notification("SABnzbd", T('Resuming'), 'download')
|
||||
self.paused = False
|
||||
growler.send_notification("SABnzbd", T('Resuming'), 'download')
|
||||
|
||||
@synchronized_CV
|
||||
def pause(self, save=True):
|
||||
|
||||
@@ -71,17 +71,27 @@ def platform_encode(p):
|
||||
|
||||
|
||||
def name_fixer(p):
|
||||
""" Return Unicode name of 8bit ASCII string, first try UTF-8, then cp1252 """
|
||||
""" Return Unicode name of 8bit ASCII string, first try UTF-8, then codepage, then cp1252 """
|
||||
if isinstance(p, unicode):
|
||||
return p
|
||||
elif isinstance(p, str):
|
||||
try:
|
||||
return p.decode('utf-8')
|
||||
except:
|
||||
return p.decode(codepage)
|
||||
try:
|
||||
return p.decode(codepage)
|
||||
except:
|
||||
return p.decode('cp1252', 'ignore')
|
||||
else:
|
||||
return p
|
||||
|
||||
def yenc_name_fixer(p):
|
||||
""" Return Unicode name of 8bit ASCII string, first try utf-8, then cp1252 """
|
||||
try:
|
||||
return p.decode('utf-8')
|
||||
except:
|
||||
return p.decode('cp1252')
|
||||
|
||||
|
||||
def is_utf8(p):
|
||||
""" Return True when p is UTF-8 or plain ASCII """
|
||||
@@ -251,7 +261,7 @@ def TRANS(p):
|
||||
if sabnzbd.WIN32:
|
||||
return p.translate(gTABLE_850_LATIN).decode('cp1252', 'replace')
|
||||
else:
|
||||
return p
|
||||
return unicoder(p)
|
||||
|
||||
|
||||
def UNTRANS(p):
|
||||
|
||||
83
sabnzbd/getipaddress.py
Normal file
83
sabnzbd/getipaddress.py
Normal file
@@ -0,0 +1,83 @@
|
||||
#!/usr/bin/python -OO
|
||||
# Copyright 2008-2016 The SABnzbd-Team <team@sabnzbd.org>
|
||||
#
|
||||
# This program is free software; you can redistribute it and/or
|
||||
# modify it under the terms of the GNU General Public License
|
||||
# as published by the Free Software Foundation; either version 2
|
||||
# of the License, or (at your option) any later version.
|
||||
#
|
||||
# This program is distributed in the hope that it will be useful,
|
||||
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
# GNU General Public License for more details.
|
||||
#
|
||||
# You should have received a copy of the GNU General Public License
|
||||
# along with this program; if not, write to the Free Software
|
||||
# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
|
||||
|
||||
"""
|
||||
sabnzbd.getipaddress
|
||||
"""
|
||||
|
||||
import socket
|
||||
import sabnzbd
|
||||
import sabnzbd.cfg
|
||||
|
||||
|
||||
def localipv4():
|
||||
try:
|
||||
s_ipv4 = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
|
||||
s_ipv4.connect(('1.2.3.4', 80)) # Option: use 100.64.1.1 (IANA-Reserved IPv4 Prefix for Shared Address Space)
|
||||
ipv4 = s_ipv4.getsockname()[0]
|
||||
s_ipv4.close()
|
||||
except:
|
||||
ipv4 = None
|
||||
pass
|
||||
return ipv4
|
||||
|
||||
def publicipv4():
|
||||
# Because of dual IPv4/IPv6 clients, finding the public ipv4 needs special attention,
|
||||
# meaning forcing IPv4 connections, and not allowing IPv6 connections
|
||||
try:
|
||||
import urllib2
|
||||
ipv4_found = False
|
||||
# we only want IPv4 resolving, so socket.AF_INET:
|
||||
result = socket.getaddrinfo(sabnzbd.cfg.selftest_host(), 80, socket.AF_INET, 0, socket.IPPROTO_TCP)
|
||||
except:
|
||||
# something very bad: no urllib2, no resolving of selftest_host, no network at all
|
||||
public_ipv4 = None
|
||||
return public_ipv4
|
||||
# we got one or more IPv4 address(es), so let's connect to them
|
||||
for item in result:
|
||||
selftest_ipv4 = item[4][0] # get next IPv4 address of sabnzbd.cfg.selftest_host()
|
||||
try:
|
||||
# put the selftest_host's IPv4 address into the URL
|
||||
req = urllib2.Request("http://" + selftest_ipv4 + "/")
|
||||
# specify the User-Agent, because certain sites refuse connections with "python urllib2" as User-Agent:
|
||||
req.add_header('User-Agent', 'SABnzbd+/%s' % sabnzbd.version.__version__ )
|
||||
# specify the Host, because we only provide the IPv4 address in the URL:
|
||||
req.add_header('Host', sabnzbd.cfg.selftest_host())
|
||||
# get the response
|
||||
public_ipv4 = urllib2.urlopen(req, timeout=2).read() # timeout 2 seconds, in case website is not accessible
|
||||
# ... check the response is indeed an IPv4 address:
|
||||
socket.inet_aton(public_ipv4) # if we got anything else than a plain IPv4 address, this will raise an exception
|
||||
# if we get here without exception, we're done:
|
||||
ipv4_found = True
|
||||
break
|
||||
except:
|
||||
# the connect OR the inet_aton raised an exception, so:
|
||||
# continue the for loop to try next server IPv4 address
|
||||
pass
|
||||
if not ipv4_found :
|
||||
public_ipv4 = None
|
||||
return public_ipv4
|
||||
|
||||
def ipv6():
|
||||
try:
|
||||
s_ipv6 = socket.socket(socket.AF_INET6, socket.SOCK_DGRAM)
|
||||
s_ipv6.connect(('2001:db8::8080', 80)) # IPv6 prefix for documentation purpose
|
||||
ipv6 = s_ipv6.getsockname()[0]
|
||||
s_ipv6.close()
|
||||
except:
|
||||
ipv6 = None
|
||||
return ipv6
|
||||
@@ -334,8 +334,7 @@ def send_notification_center(title, msg, gtype):
|
||||
tool = ncenter_path()
|
||||
if tool:
|
||||
try:
|
||||
command = [tool, '-title', title, '-message', msg, '-group', Tx(NOTIFICATION.get(gtype, 'other')),
|
||||
'-sender', 'org.sabnzbd.team']
|
||||
command = [tool, '-title', title, '-message', msg, '-group', Tx(NOTIFICATION.get(gtype, 'other'))]
|
||||
proc = subprocess.Popen(command, stdout=subprocess.PIPE, stderr=subprocess.PIPE, shell=False)
|
||||
output = proc.stdout.read()
|
||||
proc.wait()
|
||||
@@ -390,7 +389,7 @@ def send_prowl(title, msg, gtype, force=False, test=None):
|
||||
prio = sabnzbd.cfg.prowl_prio_complete()
|
||||
if gtype == 'failed':
|
||||
prio = sabnzbd.cfg.prowl_prio_failed()
|
||||
if gtype == 'disk-full':
|
||||
if gtype == 'disk_full':
|
||||
prio = sabnzbd.cfg.prowl_prio_disk_full()
|
||||
if gtype == 'warning':
|
||||
prio = sabnzbd.cfg.prowl_prio_warning()
|
||||
@@ -431,7 +430,7 @@ def send_pushover(title, msg, gtype, force=False, test=None):
|
||||
return T('Cannot send, missing required data')
|
||||
|
||||
title = Tx(NOTIFICATION.get(gtype, 'other'))
|
||||
prio = -2
|
||||
prio = -3
|
||||
|
||||
if gtype == 'startup':
|
||||
prio = sabnzbd.cfg.pushover_prio_startup()
|
||||
@@ -443,7 +442,7 @@ def send_pushover(title, msg, gtype, force=False, test=None):
|
||||
prio = sabnzbd.cfg.pushover_prio_complete()
|
||||
if gtype == 'failed':
|
||||
prio = sabnzbd.cfg.pushover_prio_failed()
|
||||
if gtype == 'disk-full':
|
||||
if gtype == 'disk_full':
|
||||
prio = sabnzbd.cfg.pushover_prio_disk_full()
|
||||
if gtype == 'warning':
|
||||
prio = sabnzbd.cfg.pushover_prio_warning()
|
||||
@@ -456,7 +455,7 @@ def send_pushover(title, msg, gtype, force=False, test=None):
|
||||
if force:
|
||||
prio = 1
|
||||
|
||||
if prio > -2:
|
||||
if prio > -3:
|
||||
try:
|
||||
conn = httplib.HTTPSConnection("api.pushover.net:443")
|
||||
conn.request("POST", "/1/messages.json", urllib.urlencode({
|
||||
@@ -541,5 +540,10 @@ def send_pushbullet(title, msg, gtype, force=False, test=None):
|
||||
|
||||
def send_windows(title, msg, gtype):
|
||||
if sabnzbd.WINTRAY:
|
||||
sabnzbd.WINTRAY.sendnotification(title, msg)
|
||||
try:
|
||||
sabnzbd.WINTRAY.sendnotification(title, msg)
|
||||
except:
|
||||
logging.info(T('Failed to send Windows notification'))
|
||||
logging.debug("Traceback: ", exc_info=True)
|
||||
return T('Failed to send Windows notification')
|
||||
return None
|
||||
|
||||
@@ -26,6 +26,7 @@ import logging
|
||||
import urllib
|
||||
import json
|
||||
import re
|
||||
import socket
|
||||
from xml.sax.saxutils import escape
|
||||
|
||||
from sabnzbd.utils.rsslib import RSS, Item
|
||||
@@ -51,6 +52,7 @@ from sabnzbd.nzbqueue import NzbQueue
|
||||
import sabnzbd.wizard
|
||||
from sabnzbd.utils.servertests import test_nntp_server_dict
|
||||
from sabnzbd.utils.sslinfo import ssl_protocols
|
||||
from sabnzbd.getipaddress import localipv4, publicipv4, ipv6
|
||||
|
||||
from sabnzbd.constants import \
|
||||
REC_RAR_VERSION, NORMAL_PRIORITY, PNFO_NZO_ID_FIELD, PNFO_REPAIR_FIELD, \
|
||||
@@ -322,7 +324,7 @@ class MainPage(object):
|
||||
# For Glitter we pre-load the JSON output
|
||||
if 'Glitter' in self.__web_dir:
|
||||
# Queue
|
||||
queue = build_queue(limit=cfg.queue_limit())[0]
|
||||
queue = build_queue(limit=cfg.queue_limit(), output='json')[0]
|
||||
queue['categories'] = info.pop('cat_list')
|
||||
queue['scripts'] = info.pop('script_list')
|
||||
|
||||
@@ -331,15 +333,16 @@ class MainPage(object):
|
||||
grand, month, week, day = BPSMeter.do.get_sums()
|
||||
history['total_size'], history['month_size'], history['week_size'], history['day_size'] = \
|
||||
to_units(grand), to_units(month), to_units(week), to_units(day)
|
||||
history['slots'], fetched_items, history['noofslots'] = build_history(limit=cfg.history_limit())
|
||||
history['slots'], fetched_items, history['noofslots'] = build_history(limit=cfg.history_limit(), output='json')
|
||||
|
||||
# Make sure the JSON works, otherwise leave empty
|
||||
try:
|
||||
info['preload_queue'] = json.dumps({'queue': remove_callable(queue)});
|
||||
info['preload_history'] = json.dumps({'history': history});
|
||||
except UnicodeDecodeError:
|
||||
info['preload_queue'] = ''
|
||||
info['preload_history'] = ''
|
||||
# We use the javascript recognized 'false'
|
||||
info['preload_queue'] = 'false'
|
||||
info['preload_history'] = 'false'
|
||||
|
||||
template = Template(file=os.path.join(self.__web_dir, 'main.tmpl'),
|
||||
filter=FILTER, searchList=[info], compilerSettings=DIRECTIVES)
|
||||
@@ -453,7 +456,15 @@ class MainPage(object):
|
||||
if cfg.api_logging():
|
||||
logging.debug('API-call from %s [%s] %s', cherrypy.request.remote.ip,
|
||||
cherrypy.request.headers.get('User-Agent', '??'), kwargs)
|
||||
if kwargs.get('mode', '') not in ('version', 'auth'):
|
||||
mode = kwargs.get('mode', '')
|
||||
if isinstance(mode, list):
|
||||
mode = mode[0]
|
||||
kwargs['mode'] = mode
|
||||
name = kwargs.get('name', '')
|
||||
if isinstance(name, list):
|
||||
name = name[0]
|
||||
kwargs['name'] = name
|
||||
if mode not in ('version', 'auth'):
|
||||
msg = check_apikey(kwargs)
|
||||
if msg:
|
||||
return msg
|
||||
@@ -468,7 +479,7 @@ class MainPage(object):
|
||||
|
||||
name = kwargs.get('name')
|
||||
if name:
|
||||
history_db = cherrypy.thread_data.history_db
|
||||
history_db = sabnzbd.connect_db()
|
||||
return ShowString(history_db.get_name(name), history_db.get_script_log(name))
|
||||
else:
|
||||
raise dcRaiser(self.__root, kwargs)
|
||||
@@ -1009,7 +1020,7 @@ class HistoryPage(object):
|
||||
msg = check_session(kwargs)
|
||||
if msg:
|
||||
return msg
|
||||
history_db = cherrypy.thread_data.history_db
|
||||
history_db = sabnzbd.connect_db()
|
||||
history_db.remove_history()
|
||||
raise queueRaiser(self.__root, kwargs)
|
||||
|
||||
@@ -1048,7 +1059,7 @@ class HistoryPage(object):
|
||||
if msg:
|
||||
return msg
|
||||
del_files = bool(int_conv(kwargs.get('del_files')))
|
||||
history_db = cherrypy.thread_data.history_db
|
||||
history_db = sabnzbd.connect_db()
|
||||
if del_files:
|
||||
del_job_files(history_db.get_failed_paths())
|
||||
history_db.remove_failed()
|
||||
@@ -1099,7 +1110,7 @@ class HistoryPage(object):
|
||||
return Protected()
|
||||
name = kwargs.get('name')
|
||||
if name:
|
||||
history_db = cherrypy.thread_data.history_db
|
||||
history_db = sabnzbd.connect_db()
|
||||
return ShowString(history_db.get_name(name), history_db.get_script_log(name))
|
||||
else:
|
||||
raise dcRaiser(self.__root, kwargs)
|
||||
@@ -1391,7 +1402,7 @@ SPECIAL_BOOL_LIST = \
|
||||
'queue_complete_pers', 'api_warnings', 'allow_64bit_tools',
|
||||
'never_repair', 'allow_streaming', 'ignore_unrar_dates', 'rss_filenames',
|
||||
'osx_menu', 'osx_speed', 'win_menu', 'use_pickle', 'allow_incomplete_nzb',
|
||||
'no_ipv6', 'keep_awake', 'empty_postproc',
|
||||
'ipv6_hosting', 'keep_awake', 'empty_postproc',
|
||||
'web_watchdog', 'wait_for_dfolder', 'warn_empty_nzb', 'enable_bonjour',
|
||||
'warn_dupl_jobs', 'backup_for_duplicates', 'enable_par_cleanup',
|
||||
'enable_https_verification', 'api_logging'
|
||||
@@ -1399,7 +1410,7 @@ SPECIAL_BOOL_LIST = \
|
||||
SPECIAL_VALUE_LIST = \
|
||||
('size_limit', 'folder_max_length', 'fsys_type', 'movie_rename_limit', 'nomedia_marker',
|
||||
'req_completion_rate', 'wait_ext_drive', 'history_limit', 'show_sysload', 'ipv6_servers',
|
||||
'rating_host', 'ipv6_test_host'
|
||||
'rating_host', 'selftest_host'
|
||||
)
|
||||
SPECIAL_LIST_LIST = \
|
||||
('rss_odd_titles', 'prio_sort_list'
|
||||
@@ -1804,9 +1815,6 @@ def handle_server(kwargs, root=None, new_svr=False):
|
||||
for kw in ('ssl', 'send_group', 'enable', 'optional'):
|
||||
if kw not in kwargs.keys():
|
||||
kwargs[kw] = None
|
||||
if 'ssl_type' in kwargs and kwargs['ssl_type'] == ssl_protocols()[0]:
|
||||
# When user selects highest protocol, make empty (default)
|
||||
kwargs['ssl_type'] = ''
|
||||
if svr and not new_svr:
|
||||
svr.set_dict(kwargs)
|
||||
else:
|
||||
@@ -2222,11 +2230,13 @@ class ConfigScheduling(object):
|
||||
actions_lng = {}
|
||||
for action in actions:
|
||||
actions_lng[action] = Ttemplate("sch-" + action)
|
||||
|
||||
actions_servers = {}
|
||||
servers = config.get_servers()
|
||||
for srv in servers:
|
||||
name = servers[srv].displayname()
|
||||
actions.append(name)
|
||||
actions_lng[name] = name
|
||||
actions_servers[srv] = servers[srv].displayname()
|
||||
|
||||
conf['actions_servers'] = actions_servers
|
||||
conf['actions'] = actions
|
||||
conf['actions_lng'] = actions_lng
|
||||
|
||||
@@ -2240,13 +2250,7 @@ class ConfigScheduling(object):
|
||||
if msg:
|
||||
return msg
|
||||
|
||||
# Create server dictionary based on displayname
|
||||
server_names = {}
|
||||
servers = config.get_servers()
|
||||
for srv in servers:
|
||||
srv = servers[srv]
|
||||
server_names[srv.displayname()] = srv.ident()[1]
|
||||
|
||||
minute = kwargs.get('minute')
|
||||
hour = kwargs.get('hour')
|
||||
days_of_week = ''.join([str(x) for x in kwargs.get('daysofweek', '')])
|
||||
@@ -2267,8 +2271,7 @@ class ConfigScheduling(object):
|
||||
arguments = 0
|
||||
elif action in _SCHED_ACTIONS:
|
||||
arguments = ''
|
||||
elif action in server_names:
|
||||
action = server_names[action]
|
||||
elif action in servers:
|
||||
if arguments == '1':
|
||||
arguments = action
|
||||
action = 'enable_server'
|
||||
@@ -2462,14 +2465,12 @@ class Status(object):
|
||||
|
||||
# Dashboard: Begin
|
||||
if not kwargs.get('skip_dashboard'):
|
||||
from sabnzbd.utils.getipaddress import localipv4, publicipv4, ipv6
|
||||
header['localipv4'] = localipv4()
|
||||
header['publicipv4'] = publicipv4()
|
||||
header['ipv6'] = ipv6()
|
||||
# Dashboard: DNS-check
|
||||
try:
|
||||
import socket
|
||||
socket.gethostbyname('www.google.com')
|
||||
socket.gethostbyname(cfg.selftest_host())
|
||||
header['dnslookup'] = "OK"
|
||||
except:
|
||||
header['dnslookup'] = None
|
||||
@@ -2659,17 +2660,12 @@ class Status(object):
|
||||
msg = check_session(kwargs)
|
||||
if msg:
|
||||
return msg
|
||||
try:
|
||||
logging.debug('Dashboard: Refresh button pressed')
|
||||
|
||||
from sabnzbd.utils.diskspeed import diskspeedmeasure
|
||||
sabnzbd.downloaddirspeed = round(diskspeedmeasure(sabnzbd.cfg.download_dir.get_path()), 1)
|
||||
sabnzbd.completedirspeed = round(diskspeedmeasure(sabnzbd.cfg.complete_dir.get_path()), 1)
|
||||
from sabnzbd.utils.diskspeed import diskspeedmeasure
|
||||
sabnzbd.downloaddirspeed = round(diskspeedmeasure(sabnzbd.cfg.download_dir.get_path()), 1)
|
||||
time.sleep(1.0)
|
||||
sabnzbd.completedirspeed = round(diskspeedmeasure(sabnzbd.cfg.complete_dir.get_path()), 1)
|
||||
|
||||
logging.debug('Dashboard: Refresh finished succesfully')
|
||||
|
||||
except:
|
||||
logging.debug('Dashboard: Refresh had a problem')
|
||||
raise dcRaiser(self.__root, kwargs) # Refresh screen
|
||||
|
||||
|
||||
@@ -2951,7 +2947,6 @@ def rss_history(url, limit=50, search=None):
|
||||
|
||||
return rss.write()
|
||||
|
||||
|
||||
def rss_warnings():
|
||||
""" Return an RSS feed with last warnings/errors """
|
||||
rss = RSS()
|
||||
@@ -2968,3 +2963,4 @@ def rss_warnings():
|
||||
rss.channel.lastBuildDate = std_time(time.time())
|
||||
rss.channel.pubDate = rss.channel.lastBuildDate
|
||||
return rss.write()
|
||||
|
||||
|
||||
@@ -446,6 +446,17 @@ def create_real_path(name, loc, path, umask=False, writable=True):
|
||||
return (False, "")
|
||||
|
||||
|
||||
def is_relative_path(p):
|
||||
""" Return True if path is relative """
|
||||
p = p.replace('\\', '/')
|
||||
if p and p[0] == '/':
|
||||
return False
|
||||
if sabnzbd.WIN32 and p and len(p) > 2:
|
||||
if p[0].isalpha() and p[1] == ':' and p[2] == '/':
|
||||
return False
|
||||
return True
|
||||
|
||||
|
||||
def windows_variant():
|
||||
""" Determine Windows variant
|
||||
Return vista_plus, x64
|
||||
@@ -1296,6 +1307,9 @@ def get_base_url(url):
|
||||
url_host = urlparse(url).hostname
|
||||
if url_host:
|
||||
url_split = url_host.split(".")
|
||||
# Exception for localhost and IPv6 addresses
|
||||
if len(url_split) < 3:
|
||||
return url_host
|
||||
return ".".join(len(url_split[-2]) < 4 and url_split[-3:] or url_split[-2:])
|
||||
else:
|
||||
return ''
|
||||
|
||||
@@ -476,7 +476,8 @@ def rar_unpack(nzo, workdir, workdir_complete, delete, one_folder, rars):
|
||||
try:
|
||||
os.remove(rar)
|
||||
except OSError:
|
||||
logging.warning(T('Deleting %s failed!'), rar)
|
||||
if os.path.exists(rar):
|
||||
logging.warning(T('Deleting %s failed!'), rar)
|
||||
|
||||
brokenrar = '%s.1' % rar
|
||||
|
||||
@@ -485,7 +486,8 @@ def rar_unpack(nzo, workdir, workdir_complete, delete, one_folder, rars):
|
||||
try:
|
||||
os.remove(brokenrar)
|
||||
except OSError:
|
||||
logging.warning(T('Deleting %s failed!'), brokenrar)
|
||||
if os.path.exists(brokenrar):
|
||||
logging.warning(T('Deleting %s failed!'), brokenrar)
|
||||
|
||||
return fail, extracted_files
|
||||
|
||||
@@ -614,6 +616,7 @@ def rar_extract_core(rarfile, numrars, one_folder, nzo, setname, extraction_path
|
||||
rarfiles = []
|
||||
fail = 0
|
||||
inrecovery = False
|
||||
lines = []
|
||||
|
||||
while 1:
|
||||
line = proc.readline()
|
||||
@@ -621,6 +624,7 @@ def rar_extract_core(rarfile, numrars, one_folder, nzo, setname, extraction_path
|
||||
break
|
||||
|
||||
line = line.strip()
|
||||
lines.append(line)
|
||||
|
||||
if line.startswith('Extracting from'):
|
||||
filename = TRANS((re.search(EXTRACTFROM_RE, line).group(1)))
|
||||
@@ -757,6 +761,7 @@ def rar_extract_core(rarfile, numrars, one_folder, nzo, setname, extraction_path
|
||||
else:
|
||||
logging.info('Skipping unrar file check due to unreliable file names or old unrar')
|
||||
|
||||
logging.debug('UNRAR output %s', '\n'.join(lines))
|
||||
nzo.fail_msg = ''
|
||||
msg = T('Unpacked %s files/folders in %s') % (str(len(extracted)), format_time_string(time() - start))
|
||||
nzo.set_unpack_info('Unpack', '[%s] %s' % (unicoder(setname), msg), set=setname)
|
||||
@@ -1032,9 +1037,9 @@ def par2_repair(parfile_nzf, nzo, workdir, setname, single):
|
||||
# Download all par2 files that haven't been downloaded yet
|
||||
readd = False
|
||||
for extrapar in parfile_nzf.extrapars[:]:
|
||||
if extrapar in nzo.files:
|
||||
parfile_nzf.extrapars.remove(extrapar)
|
||||
if extrapar not in nzo.finished_files and extrapar not in nzo.files:
|
||||
nzo.add_parfile(extrapar)
|
||||
parfile_nzf.extrapars.remove(extrapar)
|
||||
readd = True
|
||||
if readd:
|
||||
return readd, result
|
||||
@@ -1213,6 +1218,7 @@ def PAR_Verify(parfile, parfile_nzf, nzo, setname, joinables, classic=False, sin
|
||||
pars = []
|
||||
datafiles = []
|
||||
renames = {}
|
||||
reconstructed = []
|
||||
|
||||
linebuf = ''
|
||||
finished = 0
|
||||
@@ -1405,18 +1411,25 @@ def PAR_Verify(parfile, parfile_nzf, nzo, setname, joinables, classic=False, sin
|
||||
finished = 1
|
||||
|
||||
elif line.startswith('File:') and line.find('data blocks from') > 0:
|
||||
# Find out if a joinable file has been used for joining
|
||||
uline = unicoder(line)
|
||||
for jn in joinables:
|
||||
if uline.find(os.path.split(jn)[1]) > 0:
|
||||
used_joinables.append(jn)
|
||||
break
|
||||
# Special case of joined RAR files, the "of" and "from" must both be RAR files
|
||||
# This prevents the joined rars files from being seen as an extra rar-set
|
||||
m = _RE_BLOCK_FOUND.search(line)
|
||||
if m and '.rar' in m.group(1).lower() and '.rar' in m.group(2).lower():
|
||||
if m:
|
||||
workdir = os.path.split(parfile)[0]
|
||||
used_joinables.append(os.path.join(workdir, TRANS(m.group(1))))
|
||||
old_name = TRANS(m.group(1))
|
||||
new_name = TRANS(m.group(2))
|
||||
if joinables:
|
||||
# Find out if a joinable file has been used for joining
|
||||
uline = unicoder(line)
|
||||
for jn in joinables:
|
||||
if uline.find(os.path.split(jn)[1]) > 0:
|
||||
used_joinables.append(jn)
|
||||
break
|
||||
# Special case of joined RAR files, the "of" and "from" must both be RAR files
|
||||
# This prevents the joined rars files from being seen as an extra rar-set
|
||||
if '.rar' in old_name.lower() and '.rar' in new_name.lower():
|
||||
used_joinables.append(os.path.join(workdir, old_name))
|
||||
else:
|
||||
logging.debug('PAR2 will reconstruct "%s" from "%s"', new_name, old_name)
|
||||
reconstructed.append(os.path.join(workdir, old_name))
|
||||
|
||||
elif 'Could not write' in line and 'at offset 0:' in line and not classic:
|
||||
# Hit a bug in par2-tbb, retry with par2-classic
|
||||
@@ -1496,6 +1509,11 @@ def PAR_Verify(parfile, parfile_nzf, nzo, setname, joinables, classic=False, sin
|
||||
renames[name] = previous[name]
|
||||
save_data(renames, RENAMES_FILE, nzo.workpath)
|
||||
|
||||
# If successful and files were reconstructed, remove incomplete original files
|
||||
if finished and reconstructed:
|
||||
# Use 'used_joinables' as a vehicle to get rid of the files
|
||||
used_joinables.extend(reconstructed)
|
||||
|
||||
if retry_classic:
|
||||
logging.debug('Retry PAR2-joining with par2-classic')
|
||||
return PAR_Verify(parfile, parfile_nzf, nzo, setname, joinables, classic=True, single=single)
|
||||
@@ -1640,9 +1658,6 @@ def QuickCheck(set, nzo):
|
||||
nzf_list = nzo.finished_files
|
||||
|
||||
for file in md5pack:
|
||||
if sabnzbd.misc.on_cleanup_list(file, False):
|
||||
result = True
|
||||
continue
|
||||
found = False
|
||||
for nzf in nzf_list:
|
||||
if file == nzf.filename:
|
||||
@@ -1802,8 +1817,11 @@ def pre_queue(name, pp, cat, script, priority, size, groups):
|
||||
if n < len(values) and line:
|
||||
values[n] = TRANS(line)
|
||||
n += 1
|
||||
if int_conv(values[0]) < 1:
|
||||
accept = int_conv(values[0])
|
||||
if accept < 1:
|
||||
logging.info('Pre-Q refuses %s', name)
|
||||
elif accept == 2:
|
||||
logging.info('Pre-Q accepts&fails %s', name)
|
||||
else:
|
||||
logging.info('Pre-Q accepts %s', name)
|
||||
|
||||
|
||||
@@ -308,7 +308,7 @@ class NewsWrapper(object):
|
||||
self.pass_sent = True
|
||||
self.pass_ok = True
|
||||
|
||||
if code in ('501', '502') and self.user_sent:
|
||||
if code in ('501',) and self.user_sent:
|
||||
# Change to a sensible text
|
||||
code = '481'
|
||||
self.lines[0] = T('Authentication failed, check username/password.')
|
||||
|
||||
@@ -251,12 +251,13 @@ class NzbQueue(TryList):
|
||||
|
||||
nzo_ids = []
|
||||
# Aggregate nzo_ids and save each nzo
|
||||
for nzo in self.__nzo_list:
|
||||
nzo_ids.append(os.path.join(nzo.work_name, nzo.nzo_id))
|
||||
if save_nzo is None or nzo is save_nzo:
|
||||
sabnzbd.save_data(nzo, nzo.nzo_id, nzo.workpath)
|
||||
if not nzo.futuretype:
|
||||
nzo.save_to_disk()
|
||||
for nzo in self.__nzo_list[:]:
|
||||
if not nzo.deleted:
|
||||
nzo_ids.append(os.path.join(nzo.work_name, nzo.nzo_id))
|
||||
if save_nzo is None or nzo is save_nzo:
|
||||
sabnzbd.save_data(nzo, nzo.nzo_id, nzo.workpath)
|
||||
if not nzo.futuretype:
|
||||
nzo.save_to_disk()
|
||||
|
||||
sabnzbd.save_admin((QUEUE_VERSION, nzo_ids, []), QUEUE_FILE_NAME)
|
||||
|
||||
@@ -436,10 +437,10 @@ class NzbQueue(TryList):
|
||||
if nzo_id in self.__nzo_table:
|
||||
nzo = self.__nzo_table.pop(nzo_id)
|
||||
nzo.deleted = True
|
||||
if cleanup and nzo.status not in (Status.COMPLETED, Status.FAILED):
|
||||
nzo.status = Status.DELETED
|
||||
self.__nzo_list.remove(nzo)
|
||||
|
||||
sabnzbd.remove_data(nzo_id, nzo.workpath)
|
||||
|
||||
if add_to_history:
|
||||
# Create the history DB instance
|
||||
history_db = database.get_history_handle()
|
||||
@@ -451,6 +452,8 @@ class NzbQueue(TryList):
|
||||
elif cleanup:
|
||||
self.cleanup_nzo(nzo, keep_basic, del_files)
|
||||
|
||||
sabnzbd.remove_data(nzo_id, nzo.workpath)
|
||||
|
||||
if save:
|
||||
self.save(nzo)
|
||||
else:
|
||||
@@ -775,18 +778,22 @@ class NzbQueue(TryList):
|
||||
if self.__top_only:
|
||||
if self.__nzo_list:
|
||||
for nzo in self.__nzo_list:
|
||||
if nzo.status not in (Status.PAUSED, Status.GRABBING) and nzo.server_allowed(server):
|
||||
article = nzo.get_article(server, servers)
|
||||
if article:
|
||||
return article
|
||||
# Not when queue paused and not a forced item
|
||||
if (nzo.status not in (Status.PAUSED, Status.GRABBING) and not sabnzbd.downloader.Downloader.do.paused) or nzo.priority == TOP_PRIORITY:
|
||||
if nzo.server_allowed(server):
|
||||
article = nzo.get_article(server, servers)
|
||||
if article:
|
||||
return article
|
||||
|
||||
else:
|
||||
for nzo in self.__nzo_list:
|
||||
# Don't try to get an article if server is in try_list of nzo
|
||||
if not nzo.server_in_try_list(server) and nzo.status not in (Status.PAUSED, Status.GRABBING) and nzo.server_allowed(server):
|
||||
article = nzo.get_article(server, servers)
|
||||
if article:
|
||||
return article
|
||||
# Not when queue paused and not a forced item
|
||||
if (nzo.status not in (Status.PAUSED, Status.GRABBING) and not sabnzbd.downloader.Downloader.do.paused) or nzo.priority == TOP_PRIORITY:
|
||||
# Don't try to get an article if server is in try_list of nzo
|
||||
if not nzo.server_in_try_list(server) and nzo.server_allowed(server):
|
||||
article = nzo.get_article(server, servers)
|
||||
if article:
|
||||
return article
|
||||
|
||||
# No articles for this server, block server (until reset issued)
|
||||
self.add_to_try_list(server)
|
||||
@@ -807,27 +814,30 @@ class NzbQueue(TryList):
|
||||
if reset:
|
||||
self.reset_try_list()
|
||||
|
||||
if file_done:
|
||||
if nzo.next_save is None or time.time() > nzo.next_save:
|
||||
sabnzbd.save_data(nzo, nzo.nzo_id, nzo.workpath)
|
||||
BPSMeter.do.save()
|
||||
if nzo.save_timeout is None:
|
||||
nzo.next_save = None
|
||||
else:
|
||||
nzo.next_save = time.time() + nzo.save_timeout
|
||||
if nzo.status in (Status.COMPLETED, Status.DELETED):
|
||||
logging.debug('Discarding file completion %s for deleted job', filename)
|
||||
else:
|
||||
if file_done:
|
||||
if nzo.next_save is None or time.time() > nzo.next_save:
|
||||
sabnzbd.save_data(nzo, nzo.nzo_id, nzo.workpath)
|
||||
BPSMeter.do.save()
|
||||
if nzo.save_timeout is None:
|
||||
nzo.next_save = None
|
||||
else:
|
||||
nzo.next_save = time.time() + nzo.save_timeout
|
||||
|
||||
if not nzo.precheck:
|
||||
_type = nzf.type
|
||||
if not nzo.precheck:
|
||||
_type = nzf.type
|
||||
|
||||
# Only start decoding if we have a filename and type
|
||||
if filename and _type:
|
||||
Assembler.do.process((nzo, nzf))
|
||||
# Only start decoding if we have a filename and type
|
||||
if filename and _type:
|
||||
Assembler.do.process((nzo, nzf))
|
||||
|
||||
else:
|
||||
if file_has_articles(nzf):
|
||||
logging.warning(T('%s -> Unknown encoding'), filename)
|
||||
if post_done:
|
||||
self.end_job(nzo)
|
||||
else:
|
||||
if file_has_articles(nzf):
|
||||
logging.warning(T('%s -> Unknown encoding'), filename)
|
||||
if post_done:
|
||||
self.end_job(nzo)
|
||||
|
||||
def end_job(self, nzo):
|
||||
""" Send NZO to the post-processing queue """
|
||||
|
||||
@@ -82,7 +82,6 @@ class Article(TryList):
|
||||
TryList.__init__(self)
|
||||
|
||||
self.fetcher = None
|
||||
self.fetcher_priority = 0
|
||||
self.allow_fill_server = False
|
||||
|
||||
self.article = article
|
||||
@@ -703,7 +702,7 @@ class NzbObject(TryList):
|
||||
if 'A&A)' in nzb:
|
||||
# Fix needed to compensate for some dumb NZB posters
|
||||
nzb = nzb.replace('A&A)', 'A&A)')
|
||||
handler = NzbParser(self, cfg.ignore_samples() == 2 and not reuse)
|
||||
handler = NzbParser(self, False)
|
||||
parser = xml.sax.make_parser()
|
||||
parser.setFeature(xml.sax.handler.feature_external_ges, 0)
|
||||
parser.setContentHandler(handler)
|
||||
@@ -869,6 +868,12 @@ class NzbObject(TryList):
|
||||
# Set nzo save-delay to 6 sec per GB with a max of 5 min
|
||||
self.save_timeout = min(6.0 * float(self.bytes) / GIGI, 300.0)
|
||||
|
||||
# If accept&fail, fail the job
|
||||
if accept == 2:
|
||||
self.deleted = True
|
||||
sabnzbd.Assembler.do.process((self, None))
|
||||
|
||||
|
||||
def check_for_dupe(self, nzf):
|
||||
filename = nzf.filename
|
||||
|
||||
@@ -1012,7 +1017,8 @@ class NzbObject(TryList):
|
||||
if renames:
|
||||
for name in renames:
|
||||
if name in files or renames[name] in files:
|
||||
files.remove(name)
|
||||
if name in files:
|
||||
files.remove(name)
|
||||
files.append(renames[name])
|
||||
|
||||
# Looking for the longest name first, minimizes the chance on a mismatch
|
||||
@@ -1110,7 +1116,7 @@ class NzbObject(TryList):
|
||||
def pause(self):
|
||||
self.status = Status.PAUSED
|
||||
# Prevent loss of paused state when terminated
|
||||
if self.nzo_id:
|
||||
if self.nzo_id and self.status not in (Status.COMPLETED, Status.DELETED):
|
||||
sabnzbd.save_data(self, self.nzo_id, self.workpath)
|
||||
|
||||
def resume(self):
|
||||
@@ -1508,7 +1514,7 @@ class NzbObject(TryList):
|
||||
def save_to_disk(self):
|
||||
""" Save job's admin to disk """
|
||||
self.save_attribs()
|
||||
if self.nzo_id:
|
||||
if self.nzo_id and self.status not in (Status.COMPLETED, Status.DELETED):
|
||||
sabnzbd.save_data(self, self.nzo_id, self.workpath)
|
||||
|
||||
def save_attribs(self):
|
||||
|
||||
@@ -265,6 +265,8 @@ def launch_a_browser(url, force=False):
|
||||
# Must use https, because http is not available
|
||||
url = url.replace('http:', 'https:')
|
||||
|
||||
if 'localhost' in url and not cfg.ipv6_hosting():
|
||||
url = url.replace('localhost', '127.0.0.1')
|
||||
logging.info("Launching browser with %s", url)
|
||||
try:
|
||||
if url and not url.startswith('http'):
|
||||
|
||||
@@ -120,7 +120,8 @@ class PostProcessor(Thread):
|
||||
def remove(self, nzo):
|
||||
""" Remove given nzo from the queue """
|
||||
try:
|
||||
self.history_queue.remove(nzo)
|
||||
if nzo in self.history_queue:
|
||||
self.history_queue.remove(nzo)
|
||||
except:
|
||||
nzo_id = getattr(nzo, 'nzo_id', 'unknown id')
|
||||
logging.error(T('Failed to remove nzo from postproc queue (id)') + ' ' + nzo_id)
|
||||
@@ -423,7 +424,7 @@ def process_job(nzo):
|
||||
else:
|
||||
job_result = int(par_error) + int(bool(unpack_error)) * 2
|
||||
|
||||
if cfg.ignore_samples() > 0:
|
||||
if cfg.ignore_samples():
|
||||
remove_samples(workdir_complete)
|
||||
|
||||
# TV/Movie/Date Renaming code part 2 - rename and move files to parent folder
|
||||
@@ -593,7 +594,7 @@ def parring(nzo, workdir):
|
||||
|
||||
if repair_sets:
|
||||
for setname in repair_sets:
|
||||
if cfg.ignore_samples() > 0 and 'sample' in setname.lower():
|
||||
if cfg.ignore_samples() and 'sample' in setname.lower():
|
||||
continue
|
||||
if not verified.get(setname, False):
|
||||
logging.info("Running repair on set %s", setname)
|
||||
|
||||
@@ -112,7 +112,8 @@ class Rating(Thread):
|
||||
self.shutdown = False
|
||||
self.queue = OrderedSetQueue()
|
||||
try:
|
||||
(self.version, self.ratings, self.nzo_indexer_map) = sabnzbd.load_admin("Rating.sab")
|
||||
self.version, self.ratings, self.nzo_indexer_map = sabnzbd.load_admin("Rating.sab",
|
||||
silent=not cfg.rating_enable())
|
||||
if self.version == 1:
|
||||
ratings = {}
|
||||
for k, v in self.ratings.iteritems():
|
||||
|
||||
@@ -118,6 +118,7 @@ SKIN_TEXT = {
|
||||
'off' : TT('off'),
|
||||
'parameters' : TT('Parameters'), #: Config: startup parameters of SABnzbd
|
||||
'pythonVersion' : TT('Python Version'),
|
||||
'notAvailable' : TT('Not available'),
|
||||
'homePage' : TT('Home page'), #: Home page of the SABnzbd project
|
||||
'source' : TT('Source'), #: Where to find the SABnzbd sourcecode
|
||||
'or' : TT('or'), #: Used in "IRC or IRC-Webaccess"
|
||||
@@ -149,6 +150,7 @@ SKIN_TEXT = {
|
||||
'menu-wiki' : TT('Wiki'), #: Main menu item
|
||||
'menu-forums' : TT('Forum'), #: Main menu item
|
||||
'menu-irc' : TT('IRC'), #: Main menu item
|
||||
'menu-issues' : TT('Issues'), #: Main menu item
|
||||
'cmenu-general' : TT('General'), #: Main menu item
|
||||
'cmenu-folders' : TT('Folders'), #: Main menu item
|
||||
'cmenu-switches' : TT('Switches'), #: Main menu item
|
||||
@@ -271,7 +273,7 @@ SKIN_TEXT = {
|
||||
'warning' : TT('Warning'), #: Status page, table column header, actual message
|
||||
'warnings' : TT('Warnings'), #: Footer: indicator of warnings
|
||||
'enabled' : TT('Enabled'), #: Status page, indicator that server is enabled
|
||||
|
||||
|
||||
# Dashboard
|
||||
'dashboard-title' : TT('Dashboard'),
|
||||
'dashboard-connectionError' : TT('Connection failed!'),
|
||||
@@ -337,7 +339,7 @@ SKIN_TEXT = {
|
||||
'opt-bandwidth_perc' : TT('Percentage of line speed'),
|
||||
'explain-bandwidth_perc' : TT('Which percentage of the linespeed should SABnzbd use, e.g. 50'),
|
||||
'opt-cache_limitstr' : TT('Article Cache Limit'),
|
||||
'explain-cache_limitstr' : TT('Cache articles in memory to reduce disk access.<br /><i>In bytes, optionally follow with K,M,G. For example: "64M" or "128M"</i>'),
|
||||
'explain-cache_limitstr' : TT('Cache articles in memory to reduce disk access.<br /><i>In bytes, optionally follow with K,M,G. For example: "64M" or "128M"</i>').replace("64M", "256M").replace("128M", "512M"),
|
||||
'opt-cleanup_list' : TT('Cleanup List'),
|
||||
'explain-cleanup_list' : TT('List of file extensions that should be deleted after download.<br />For example: <b>nfo</b> or <b>nfo, sfv</b>'),
|
||||
'button-saveChanges' : TT('Save Changes'),
|
||||
@@ -805,12 +807,12 @@ SKIN_TEXT = {
|
||||
'Glitter-confirmClearWarnings' : TT('Are you sure?'),
|
||||
'Glitter-confirmClearDownloads' : TT('Are you sure?'),
|
||||
'Glitter-confirmClear1Download' : TT('Are you sure?'),
|
||||
'Glitter-grabbing' : TT('Grabbing NZB...'),
|
||||
'Glitter-updateAvailable' : TT('Update Available!'),
|
||||
'Glitter-noLocalStorage' : TT('LocalStorage (cookies) are disabled in your browser, interface settings will be lost after you close the browser!'), #: Don't translate LocalStorage
|
||||
'Glitter-custom' : TT('Custom'),
|
||||
'Glitter-confirmDeleteQueue' : TT('Confirm Queue Deletions'),
|
||||
'Glitter-confirmDeleteHistory' : TT('Confirm History Deletions'),
|
||||
'Glitter-pausePrompt': TT('How long or untill when do you want to pause? (in English!)'),
|
||||
'Glitter-pausePrompt': TT('How long or untill when do you want to pause? (in English!)'),
|
||||
'Glitter-pausePromptFail': TT('Sorry, we could not interpret that. Try again.'),
|
||||
'Glitter-pauseFor' : TT('Pause for...'),
|
||||
'Glitter-sortAgeAsc' : TT('Sort by Age <small>Oldest→Newest</small>'),
|
||||
|
||||
@@ -40,6 +40,7 @@ class TryList:
|
||||
|
||||
def __init__(self):
|
||||
self.__try_list = []
|
||||
self.fetcher_priority = 0
|
||||
|
||||
@synchronized(TRYLIST_LOCK)
|
||||
def server_in_try_list(self, server):
|
||||
@@ -67,3 +68,4 @@ class TryList:
|
||||
""" Clean the list """
|
||||
if self.__try_list:
|
||||
self.__try_list = []
|
||||
self.fetcher_priority = 0
|
||||
|
||||
@@ -124,6 +124,9 @@ class URLGrabber(Thread):
|
||||
elif '401' in error1 or 'unauthorized' in error1:
|
||||
msg = T('Unauthorized access')
|
||||
retry = False
|
||||
elif '404' in error1:
|
||||
msg = T('File not on server')
|
||||
retry = False
|
||||
|
||||
new_url = dereferring(url, fn)
|
||||
if new_url:
|
||||
@@ -201,6 +204,9 @@ class URLGrabber(Thread):
|
||||
data = fn.read()
|
||||
fn.close()
|
||||
|
||||
# Sanatize filename first
|
||||
filename = misc.sanitize_filename(filename)
|
||||
|
||||
# Write data to temp file
|
||||
path = os.path.join(cfg.admin_dir.get_path(), FUTURE_Q_FOLDER)
|
||||
path = os.path.join(path, filename)
|
||||
|
||||
@@ -3,40 +3,59 @@
|
||||
import time
|
||||
import os
|
||||
import sys
|
||||
import logging
|
||||
|
||||
_DUMP_DATA = '*' * 10000
|
||||
|
||||
def writetofile(filename, mysizeMB):
|
||||
# writes string to specified file repeat delay, until mysizeMB is reached. Then deletes file
|
||||
mystring = "The quick brown fox jumps over the lazy dog"
|
||||
writeloops = int(1000000 * mysizeMB / len(mystring))
|
||||
# writes string to specified file repeat delay, until mysizeMB is reached.
|
||||
writeloops = int(1024 * 1024 * mysizeMB / len(_DUMP_DATA))
|
||||
try:
|
||||
f = open(filename, 'w')
|
||||
except:
|
||||
# no better idea than:
|
||||
raise
|
||||
for x in range(0, writeloops):
|
||||
f.write(mystring)
|
||||
logging.debug('Cannot create file %s', filename)
|
||||
logging.debug("Traceback: ", exc_info=True)
|
||||
return False
|
||||
|
||||
try:
|
||||
for x in xrange(writeloops):
|
||||
f.write(_DUMP_DATA)
|
||||
except:
|
||||
logging.debug('Cannot write to file %s', filename)
|
||||
logging.debug("Traceback: ", exc_info=True)
|
||||
return False
|
||||
f.close()
|
||||
os.remove(filename)
|
||||
return True
|
||||
|
||||
|
||||
def diskspeedmeasure(dirname):
|
||||
# returns writing speed to dirname in MB/s
|
||||
# method: keep writing a file, until 0.5 seconds is passed. Then divide bytes written by time passed
|
||||
filesize = 1 # MB
|
||||
filesize = 10 # MB
|
||||
maxtime = 0.5 # sec
|
||||
filename = os.path.join(dirname, 'outputTESTING.txt')
|
||||
|
||||
if os.name == 'nt':
|
||||
# On Windows, this crazy action is needed to
|
||||
# avoid a "permission denied" error
|
||||
try:
|
||||
os.system('echo Hi >%s' % filename)
|
||||
except:
|
||||
pass
|
||||
|
||||
start = time.time()
|
||||
loopcounter = 0
|
||||
while True:
|
||||
try:
|
||||
writetofile(filename, filesize)
|
||||
except:
|
||||
return None
|
||||
if not writetofile(filename, filesize):
|
||||
return 0
|
||||
loopcounter += 1
|
||||
diff = time.time() - start
|
||||
if diff > maxtime:
|
||||
break
|
||||
try:
|
||||
os.remove(filename)
|
||||
except:
|
||||
pass
|
||||
return (loopcounter * filesize) / diff
|
||||
|
||||
|
||||
|
||||
@@ -1,43 +0,0 @@
|
||||
#!/usr/bin/python -OO
|
||||
|
||||
import socket
|
||||
|
||||
|
||||
def localipv4():
|
||||
try:
|
||||
s_ipv4 = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
|
||||
s_ipv4.connect(('1.2.3.4', 80)) # Option: use 100.64.1.1 (IANA-Reserved IPv4 Prefix for Shared Address Space)
|
||||
ipv4 = s_ipv4.getsockname()[0]
|
||||
s_ipv4.close()
|
||||
except:
|
||||
ipv4 = None
|
||||
pass
|
||||
return ipv4
|
||||
|
||||
|
||||
def publicipv4():
|
||||
try:
|
||||
import urllib2
|
||||
f = urllib2.urlopen("http://api.ipify.org", timeout=2) # timeout 2 seconds, in case website is not accessible
|
||||
public_ipv4 = f.read()
|
||||
socket.inet_aton(public_ipv4) # if we got anything else than a plain IPv4 address, this will raise an exception
|
||||
except:
|
||||
public_ipv4 = None
|
||||
pass
|
||||
return public_ipv4
|
||||
|
||||
|
||||
def ipv6():
|
||||
try:
|
||||
s_ipv6 = socket.socket(socket.AF_INET6, socket.SOCK_DGRAM)
|
||||
s_ipv6.connect(('2001:db8::8080', 80)) # IPv6 prefix for documentation purpose
|
||||
ipv6 = s_ipv6.getsockname()[0]
|
||||
s_ipv6.close()
|
||||
except:
|
||||
ipv6 = None
|
||||
return ipv6
|
||||
|
||||
if __name__ == '__main__':
|
||||
print localipv4()
|
||||
print publicipv4()
|
||||
print ipv6()
|
||||
@@ -1,7 +1,5 @@
|
||||
|
||||
_ALL_PROTOCOLS = ('t12', 't11', 't1', 'v23', 'v3', 'v2')
|
||||
_SSL_PROTOCOLS = {}
|
||||
|
||||
def ssl_potential():
|
||||
''' Return a list of potentially supported SSL protocols'''
|
||||
try:
|
||||
@@ -47,17 +45,24 @@ try:
|
||||
except ImportError:
|
||||
SSL = None
|
||||
|
||||
|
||||
def ssl_method(method):
|
||||
''' Translate SSL acronym to a method value '''
|
||||
if method in _SSL_PROTOCOLS:
|
||||
return _SSL_PROTOCOLS[method]
|
||||
else:
|
||||
return _SSL_PROTOCOLS[0]
|
||||
# The default is "negotiate a protocol"
|
||||
try:
|
||||
return SSL.SSLv23_METHOD
|
||||
except AttributeError:
|
||||
return _SSL_PROTOCOLS[0]
|
||||
|
||||
|
||||
def ssl_protocols():
|
||||
''' Return acronyms for SSL protocols, highest quality first '''
|
||||
return [p for p in _ALL_PROTOCOLS if p in _SSL_PROTOCOLS]
|
||||
|
||||
|
||||
def ssl_version():
|
||||
if SSL:
|
||||
try:
|
||||
@@ -72,8 +77,19 @@ def ssl_version():
|
||||
return None
|
||||
|
||||
|
||||
def pyopenssl_version():
|
||||
if SSL:
|
||||
try:
|
||||
import OpenSSL
|
||||
return OpenSSL.__version__
|
||||
except ImportError:
|
||||
return 'No pyOpenSSL installed'
|
||||
else:
|
||||
return None
|
||||
|
||||
if __name__ == '__main__':
|
||||
|
||||
print 'SSL version: %s' % ssl_version()
|
||||
print 'pyOpenSSL version: %s' % pyopenssl_version()
|
||||
print 'Potentials: %s' % ssl_potential()
|
||||
print 'Actuals: %s' % ssl_protocols()
|
||||
|
||||
Reference in New Issue
Block a user