mirror of
https://github.com/sabnzbd/sabnzbd.git
synced 2026-01-03 21:20:24 -05:00
Compare commits
15 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
82857afed6 | ||
|
|
4e7f0a6a1e | ||
|
|
2a113f7f58 | ||
|
|
6b8b9e0238 | ||
|
|
1e3e4b4118 | ||
|
|
87dfbe34d4 | ||
|
|
c56bcfaf61 | ||
|
|
a947a1d88b | ||
|
|
ad0d5726ec | ||
|
|
c52ce58b6d | ||
|
|
a90356c6e7 | ||
|
|
5c78c7855b | ||
|
|
915ee650ee | ||
|
|
58bd12b083 | ||
|
|
ecc334360a |
@@ -1,5 +1,5 @@
|
||||
*******************************************
|
||||
*** This is SABnzbd 2.3.3 ***
|
||||
*** This is SABnzbd 2.3.4 ***
|
||||
*******************************************
|
||||
SABnzbd is an open-source cross-platform binary newsreader.
|
||||
It simplifies the process of downloading from Usenet dramatically,
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
SABnzbd 2.3.3
|
||||
SABnzbd 2.3.4
|
||||
|
||||
-------------------------------------------------------------------------------
|
||||
0) LICENSE
|
||||
|
||||
4
PKG-INFO
4
PKG-INFO
@@ -1,7 +1,7 @@
|
||||
Metadata-Version: 1.0
|
||||
Name: SABnzbd
|
||||
Version: 2.3.3
|
||||
Summary: SABnzbd-2.3.3
|
||||
Version: 2.3.4
|
||||
Summary: SABnzbd-2.3.4
|
||||
Home-page: https://sabnzbd.org
|
||||
Author: The SABnzbd Team
|
||||
Author-email: team@sabnzbd.org
|
||||
|
||||
46
README.mkd
46
README.mkd
@@ -1,38 +1,18 @@
|
||||
Release Notes - SABnzbd 2.3.3
|
||||
Release Notes - SABnzbd 2.3.4
|
||||
=========================================================
|
||||
|
||||
## Changes since 2.3.2
|
||||
- Introduce and enforce "host_whitelist" to reject DNS Rebinding attacks.
|
||||
If you access SABnzbd from a non-standard URL, you will need to add
|
||||
the hostname. More info: https://sabnzbd.org/hostname-check
|
||||
- SABYenc updated to 3.3.5 to fix false-positive CRC errors
|
||||
- SSL-Ciphers can now be set per-server
|
||||
- Failed URL fetches also trigger post-processing script (if configured)
|
||||
- Added "max_url_retries" to set maximum retries of URL fetching
|
||||
- Added "ignore_empty_files" option to not warn on empty files in NZB
|
||||
- Added "X-Frame-Options" HTTP-header to prevent click-jacking
|
||||
- Added "httpOnly" HTTP-header to prevent script cookie access
|
||||
- Extended SAN list of newly generated self-signed certificates
|
||||
- Indicate that SMPL-skin is no longer supported
|
||||
- Removed undocumented "callback" option from API calls
|
||||
- macOS: 64bit version of unrar instead of 32bit
|
||||
- Windows: Set process priority of external processes (unpack/repair)
|
||||
- Windows: Default external process priority increased to "Normal"
|
||||
|
||||
## Bugfixes since 2.3.2
|
||||
- NZB's can be added via command-line but this was not shown in "--help"
|
||||
- Only show bad-SSL-warning if it was actually tested
|
||||
- Language-change via API did not directly change display language
|
||||
- Cheetah 3 is also accepted as template engine
|
||||
- Correctly indicate that 99 is the maximum server priority
|
||||
- Results of unpacked zip/7zip files were not sorted
|
||||
- Joining of split files was limited to 999 files
|
||||
- Media files with "password" in filename were detected as encrypted
|
||||
- Servers that could not be DNS-resolved could block the queue
|
||||
- Detect '502 Byte limit exceeded' as payment problem
|
||||
- Server load-balancing setting was ignored when testing server
|
||||
- Windows: MultiPar checksum errors during repair would result in crash
|
||||
- Windows: Update 7zip to 18.01
|
||||
## Changes since 2.3.3
|
||||
- Device hostname in hostname-verification always lowercased
|
||||
- Hostnames ending in ".local" are always accepted
|
||||
- URLGrabber would not always detect correct filename
|
||||
- URLGrabber would ignore some successful downloads
|
||||
- Always send NNTP QUIT after server-test
|
||||
- Added option "--disable-file-log" to disable file-based logging
|
||||
- Added CORS-header to API
|
||||
- Windows: Service compatibility with Windows 10 April update
|
||||
- Windows: Update Python to 2.7.15
|
||||
- Windows: Update 7zip to 18.05
|
||||
- macOS: Restore compatibility with El Capitan (10.11)
|
||||
|
||||
## Upgrading from 2.2.x and older
|
||||
- Finish queue
|
||||
|
||||
46
SABnzbd.py
46
SABnzbd.py
@@ -204,6 +204,7 @@ def print_help():
|
||||
print " --ipv6_hosting <0|1> Listen on IPv6 address [::1] [*]"
|
||||
print " --no-login Start with username and password reset"
|
||||
print " --log-all Log all article handling (for developers)"
|
||||
print " --disable-file-log Logging is only written to console"
|
||||
print " --console Force console logging for OSX app"
|
||||
print " --new Run a new instance of SABnzbd"
|
||||
print ""
|
||||
@@ -760,7 +761,7 @@ def commandline_handler(frozen=True):
|
||||
opts, args = getopt.getopt(info, "phdvncwl:s:f:t:b:2:",
|
||||
['pause', 'help', 'daemon', 'nobrowser', 'clean', 'logging=',
|
||||
'weblogging', 'server=', 'templates', 'ipv6_hosting=',
|
||||
'template2', 'browser=', 'config-file=', 'force',
|
||||
'template2', 'browser=', 'config-file=', 'force', 'disable-file-log',
|
||||
'version', 'https=', 'autorestarted', 'repair', 'repair-all',
|
||||
'log-all', 'no-login', 'pid=', 'new', 'console', 'pidfile=',
|
||||
# Below Win32 Service options
|
||||
@@ -823,6 +824,7 @@ def main():
|
||||
cherrypylogging = None
|
||||
clean_up = False
|
||||
logging_level = None
|
||||
no_file_log = False
|
||||
web_dir = None
|
||||
vista_plus = False
|
||||
win64 = False
|
||||
@@ -896,6 +898,8 @@ def main():
|
||||
pause = True
|
||||
elif opt in ('--log-all',):
|
||||
sabnzbd.LOG_ALL = True
|
||||
elif opt in ('--disable-file-log'):
|
||||
no_file_log = True
|
||||
elif opt in ('--no-login',):
|
||||
no_login = True
|
||||
elif opt in ('--pid',):
|
||||
@@ -1076,11 +1080,7 @@ def main():
|
||||
# We found a port, now we never check again
|
||||
sabnzbd.cfg.fixed_ports.set(True)
|
||||
|
||||
if logging_level is None:
|
||||
logging_level = sabnzbd.cfg.log_level()
|
||||
else:
|
||||
sabnzbd.cfg.log_level.set(logging_level)
|
||||
|
||||
# Logging-checks
|
||||
logdir = sabnzbd.cfg.log_dir.get_path()
|
||||
if fork and not logdir:
|
||||
print "Error:"
|
||||
@@ -1099,19 +1099,24 @@ def main():
|
||||
# Prevent the logger from raising exceptions
|
||||
# primarily to reduce the fallout of Python issue 4749
|
||||
logging.raiseExceptions = 0
|
||||
|
||||
# Log-related constants we always need
|
||||
if logging_level is None:
|
||||
logging_level = sabnzbd.cfg.log_level()
|
||||
else:
|
||||
sabnzbd.cfg.log_level.set(logging_level)
|
||||
sabnzbd.LOGFILE = os.path.join(logdir, DEF_LOG_FILE)
|
||||
logformat = '%(asctime)s::%(levelname)s::[%(module)s:%(lineno)d] %(message)s'
|
||||
logger.setLevel(LOGLEVELS[logging_level + 1])
|
||||
|
||||
try:
|
||||
rollover_log = logging.handlers.RotatingFileHandler(
|
||||
sabnzbd.LOGFILE, 'a+',
|
||||
sabnzbd.cfg.log_size.get_int(),
|
||||
sabnzbd.cfg.log_backups())
|
||||
|
||||
logformat = '%(asctime)s::%(levelname)s::[%(module)s:%(lineno)d] %(message)s'
|
||||
rollover_log.setFormatter(logging.Formatter(logformat))
|
||||
sabnzbd.LOGHANDLER = rollover_log
|
||||
logger.addHandler(rollover_log)
|
||||
logger.setLevel(LOGLEVELS[logging_level + 1])
|
||||
if not no_file_log:
|
||||
rollover_log = logging.handlers.RotatingFileHandler(
|
||||
sabnzbd.LOGFILE, 'a+',
|
||||
sabnzbd.cfg.log_size.get_int(),
|
||||
sabnzbd.cfg.log_backups())
|
||||
rollover_log.setFormatter(logging.Formatter(logformat))
|
||||
logger.addHandler(rollover_log)
|
||||
|
||||
except IOError:
|
||||
print "Error:"
|
||||
@@ -1141,6 +1146,8 @@ def main():
|
||||
console.setLevel(LOGLEVELS[logging_level + 1])
|
||||
console.setFormatter(logging.Formatter(logformat))
|
||||
logger.addHandler(console)
|
||||
if no_file_log:
|
||||
logging.info('Console logging only')
|
||||
if noConsoleLoggingOSX:
|
||||
logging.info('Console logging for OSX App disabled')
|
||||
so = file('/dev/null', 'a+')
|
||||
@@ -1365,8 +1372,11 @@ def main():
|
||||
staticcfg = {'tools.staticdir.on': True, 'tools.staticdir.dir': os.path.join(sabnzbd.WEB_DIR_CONFIG, 'staticcfg'), 'tools.staticdir.content_types': forced_mime_types}
|
||||
wizard_static = {'tools.staticdir.on': True, 'tools.staticdir.dir': os.path.join(sabnzbd.WIZARD_DIR, 'static'), 'tools.staticdir.content_types': forced_mime_types}
|
||||
|
||||
appconfig = {'/api': {'tools.basic_auth.on': False},
|
||||
'/rss': {'tools.basic_auth.on': False},
|
||||
appconfig = {'/api': {
|
||||
'tools.basic_auth.on': False,
|
||||
'tools.response_headers.on': True,
|
||||
'tools.response_headers.headers': [('Access-Control-Allow-Origin', '*')]
|
||||
},
|
||||
'/static': static,
|
||||
'/wizard/static': wizard_static,
|
||||
'/favicon.ico': {'tools.staticfile.on': True, 'tools.staticfile.filename': os.path.join(sabnzbd.WEB_DIR_CONFIG, 'staticcfg', 'ico', 'favicon.ico')},
|
||||
|
||||
BIN
osx/unrar/unrar
BIN
osx/unrar/unrar
Binary file not shown.
@@ -26,7 +26,7 @@ from sabnzbd.constants import DEF_HOST, DEF_PORT, DEF_STDINTF, DEF_ADMIN_DIR, \
|
||||
|
||||
from sabnzbd.config import OptionBool, OptionNumber, OptionPassword, \
|
||||
OptionDir, OptionStr, OptionList, no_nonsense, \
|
||||
validate_octal, validate_safedir, \
|
||||
validate_octal, validate_safedir, all_lowercase, \
|
||||
create_api_key, validate_notempty
|
||||
|
||||
##############################################################################
|
||||
@@ -280,7 +280,7 @@ wait_ext_drive = OptionNumber('misc', 'wait_ext_drive', 5, 1, 60)
|
||||
marker_file = OptionStr('misc', 'nomedia_marker', '')
|
||||
ipv6_servers = OptionNumber('misc', 'ipv6_servers', 1, 0, 2)
|
||||
url_base = OptionStr('misc', 'url_base', '/sabnzbd')
|
||||
host_whitelist = OptionList('misc', 'host_whitelist')
|
||||
host_whitelist = OptionList('misc', 'host_whitelist', validation=all_lowercase)
|
||||
max_url_retries = OptionNumber('misc', 'max_url_retries', 10, 1)
|
||||
|
||||
##############################################################################
|
||||
|
||||
@@ -1054,6 +1054,14 @@ def no_nonsense(value):
|
||||
return None, value
|
||||
|
||||
|
||||
def all_lowercase(value):
|
||||
""" Lowercase everything! """
|
||||
if isinstance(value, list):
|
||||
# If list, for each item
|
||||
return None, [item.lower() for item in value]
|
||||
return None, value.lower()
|
||||
|
||||
|
||||
def validate_octal(value):
|
||||
""" Check if string is valid octal number """
|
||||
if not value:
|
||||
|
||||
@@ -174,6 +174,11 @@ def check_hostname():
|
||||
if host in cfg.host_whitelist():
|
||||
return True
|
||||
|
||||
# Fine if ends with ".local" or ".local.", aka mDNS name
|
||||
# See rfc6762 Multicast DNS
|
||||
if host.endswith(('.local', '.local.')):
|
||||
return True
|
||||
|
||||
# Ohoh, bad
|
||||
log_warning_and_ip(T('Refused connection with hostname "%s" from:') % host)
|
||||
return False
|
||||
|
||||
@@ -189,6 +189,7 @@ class URLGrabber(Thread):
|
||||
if item in _RARTING_FIELDS:
|
||||
nzo_info[item] = value
|
||||
|
||||
# Get filename from Content-Disposition header
|
||||
if not filename and "filename=" in value:
|
||||
filename = value[value.index("filename=") + 9:].strip(';').strip('"')
|
||||
|
||||
@@ -209,7 +210,12 @@ class URLGrabber(Thread):
|
||||
continue
|
||||
|
||||
if not filename:
|
||||
filename = os.path.basename(url)
|
||||
filename = os.path.basename(urllib2.unquote(url))
|
||||
|
||||
# URL was redirected, maybe the redirect has better filename?
|
||||
# Check if the original URL has extension
|
||||
if url != fetch_request.url and misc.get_ext(filename) not in VALID_NZB_FILES:
|
||||
filename = os.path.basename(urllib2.unquote(fetch_request.url))
|
||||
elif '&nzbname=' in filename:
|
||||
# Sometimes the filename contains the full URL, duh!
|
||||
filename = filename[filename.find('&nzbname=') + 9:]
|
||||
@@ -361,13 +367,6 @@ def _analyse(fetch_request, url, future_nzo):
|
||||
logging.debug('No usable response from indexer, retry after %s sec', when)
|
||||
return None, msg, True, when, data
|
||||
|
||||
# Check for an error response
|
||||
if not fetch_request or fetch_request.msg != 'OK':
|
||||
# Increasing wait-time in steps for standard errors
|
||||
when = DEF_TIMEOUT * (future_nzo.url_tries + 1)
|
||||
logging.debug('Received nothing from indexer, retry after %s sec', when)
|
||||
return None, fetch_request.msg, True, when, data
|
||||
|
||||
return fetch_request, fetch_request.msg, False, 0, data
|
||||
|
||||
|
||||
|
||||
@@ -119,8 +119,12 @@ def test_nntp_server(host, port, server=None, username=None, password=None, ssl=
|
||||
nw.clear_data()
|
||||
nw.recv_chunk(block=True)
|
||||
except:
|
||||
# Some internal error, not always safe to close connection
|
||||
return False, unicode(sys.exc_info()[1])
|
||||
|
||||
# Close the connection
|
||||
nw.terminate(quit=True)
|
||||
|
||||
if nw.status_code == '480':
|
||||
return False, T('Server requires username and password.')
|
||||
|
||||
@@ -136,5 +140,3 @@ def test_nntp_server(host, port, server=None, username=None, password=None, ssl=
|
||||
else:
|
||||
return False, T('Could not determine connection result (%s)') % nntp_to_msg(nw.data)
|
||||
|
||||
# Close the connection
|
||||
nw.terminate(quit=True)
|
||||
|
||||
@@ -4,5 +4,5 @@
|
||||
|
||||
# You MUST use double quotes (so " and not ')
|
||||
|
||||
__version__ = "2.3.3"
|
||||
__baseline__ = "1f04343a4d9453050d6c36087ee2e2fd6c5eee32"
|
||||
__version__ = "2.3.4"
|
||||
__baseline__ = "2a113f7f588fe78c5dcc3453db31e0ec540efd60"
|
||||
|
||||
@@ -50,7 +50,7 @@ class MailSlot(object):
|
||||
|
||||
def connect(self):
|
||||
""" Connect to existing Mailslot so that writing is possible """
|
||||
slot = r'\\%s\%s' % (os.environ['COMPUTERNAME'], MailSlot.slotname)
|
||||
slot = r'\\.\%s' % MailSlot.slotname
|
||||
self.handle = CreateFile(slot, GENERIC_WRITE, FILE_SHARE_READ, 0, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, 0)
|
||||
return self.handle != -1
|
||||
|
||||
|
||||
BIN
win/7zip/7za.exe
BIN
win/7zip/7za.exe
Binary file not shown.
Reference in New Issue
Block a user