mirror of
https://github.com/sabnzbd/sabnzbd.git
synced 2026-01-03 21:20:24 -05:00
Compare commits
10 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
555d8418e7 | ||
|
|
8c22e35da4 | ||
|
|
d32cf57c75 | ||
|
|
6d9242ebc5 | ||
|
|
cbc4f6a964 | ||
|
|
2a3b2b9556 | ||
|
|
53a219f12b | ||
|
|
48519dcfa0 | ||
|
|
92542c58fe | ||
|
|
7eafe730f9 |
4
PKG-INFO
4
PKG-INFO
@@ -1,7 +1,7 @@
|
||||
Metadata-Version: 1.0
|
||||
Name: SABnzbd
|
||||
Version: 1.2.RC1
|
||||
Summary: SABnzbd-1.2.1RC1
|
||||
Version: 1.2.2
|
||||
Summary: SABnzbd-1.2.2
|
||||
Home-page: http://sabnzbd.org
|
||||
Author: The SABnzbd Team
|
||||
Author-email: team@sabnzbd.org
|
||||
|
||||
43
README.mkd
43
README.mkd
@@ -1,39 +1,40 @@
|
||||
Release Notes - SABnzbd 1.2.1RC1
|
||||
Release Notes - SABnzbd 1.2.2
|
||||
==============================================
|
||||
|
||||
## What's new in 1.2.1 RC1
|
||||
- On Windows paths passed to scripts were in \\?\ notation
|
||||
- New self-signed certificates now list local IP in SAN-list
|
||||
- Retry rename 3x before falling back to copy during "Moving"
|
||||
- Fix RSS page problems with missing fields
|
||||
- Passwords were not parsed correctly from filenames
|
||||
- Catch several SSL errors of the webserver
|
||||
- Multi-feed RSS will not stop if only 1 feed is not functioning
|
||||
- More incorrectly labeled some downloads as Encrypted
|
||||
## Bug fix in 1.2.2
|
||||
- Windows: job-directory incorrectly passed to PostProcessing-script
|
||||
|
||||
|
||||
## What's new in 1.2.1 Beta 1
|
||||
## What's new in 1.2.1
|
||||
- QuickCheck will perform fast rename of obfuscated posts
|
||||
- RSS Downloaded page now shows icon to indicate source
|
||||
- HTML tags are filtered from single-line script output
|
||||
|
||||
## Bug fixes in 1.2.1 Beta 1
|
||||
- Fix crashing Assembler
|
||||
- Cloaked files (RAR within RAR) were not detected anymore
|
||||
- 'Only Download Top of Queue' was broken for a long time
|
||||
- Incorrectly labeled some downloads as Encrypted
|
||||
- RSS reading could fail on newznab attributes
|
||||
- Incorrectly marking jobs with folders inside as failed
|
||||
- New self-signed certificates now list local IP in SAN-list
|
||||
- Handle jobs on Windows with forbidden names (Con.*, Aux.*,..)
|
||||
|
||||
## Bug fixes in 1.2.1
|
||||
- Fix crashing Assembler
|
||||
- 'Only Download Top of Queue' was broken for a long time
|
||||
- Cloaked files (RAR within RAR) were not detected anymore
|
||||
- Incorrectly labeled some downloads as Encrypted
|
||||
- Passwords were not parsed correctly from filenames
|
||||
- RSS reading could fail on missing attributes
|
||||
- Multi-feed RSS will not stop if only 1 feed is not functioning
|
||||
- Duplicate detection set to Fail would not work for RSS feeds
|
||||
- Incorrectly marking jobs with folders inside as failed
|
||||
- Categories were not matched properly if a list of tags was set
|
||||
- PostProcessing-script was not called on Accept&Fail or Dupe detect
|
||||
- Support for newer par2cmdline(-mt) versions that need -B parameter
|
||||
- Some newsservers would timeout when connecting
|
||||
- Duplicate detection set to Fail would not work for RSS feeds
|
||||
- More robust detection of execute permissions for scripts
|
||||
- CPU type reporting on Windows and macOS
|
||||
- Failed to start with some localhost configs
|
||||
- Removed some more stalling issues
|
||||
- Retry rename 3x before falling back to copy during "Moving"
|
||||
- Catch several SSL errors of the webserver
|
||||
- Disk-space information is now only checked every 10 seconds
|
||||
|
||||
## Translations
|
||||
- Many translations updated, thanks to our translators!
|
||||
|
||||
## About
|
||||
SABnzbd is an open-source cross-platform binary newsreader.
|
||||
|
||||
@@ -131,7 +131,7 @@
|
||||
<div class="col-sm-6" data-bind="visible: hasDiskStatusInfo">
|
||||
<span data-bind="text: statusInfo.downloaddirspeed()"></span> MB/s
|
||||
<a href="#" class="diskspeed-button" data-bind="click: testDiskSpeed" data-tooltip="true" data-placement="right" title="$T('dashboard-repeatTest')"><span class="glyphicon glyphicon-repeat"></span></a>
|
||||
<small>(<span data-bind="truncatedText: statusInfo.downloaddir, length: 24"></span>)</small>
|
||||
<small>(<span data-bind="truncatedText: statusInfo.downloaddir, length: 24, attr: { 'data-original-title': statusInfo.downloaddir }" data-tooltip="true"></span>)</small>
|
||||
</div>
|
||||
<div class="col-sm-6 col-loading" data-bind="visible: !hasDiskStatusInfo()">$T('Glitter-loading')<span class="loader-dot-one">.</span><span class="loader-dot-two">.</span><span class="loader-dot-three">.</span></div>
|
||||
</div>
|
||||
@@ -140,7 +140,7 @@
|
||||
<div class="col-sm-6" data-bind="visible: hasDiskStatusInfo">
|
||||
<span data-bind="text: statusInfo.completedirspeed()"></span> MB/s
|
||||
<a href="#" class="diskspeed-button" data-bind="click: testDiskSpeed" data-tooltip="true" data-placement="right" title="$T('dashboard-repeatTest')"><span class="glyphicon glyphicon-repeat"></span></a>
|
||||
<small>(<span data-bind="truncatedText: statusInfo.completedir, length: 24"></span>)</small>
|
||||
<small>(<span data-bind="truncatedText: statusInfo.completedir, length: 24, attr: { 'data-original-title': statusInfo.completedir }" data-tooltip="true"></span>)</small>
|
||||
</div>
|
||||
<div class="col-sm-6 col-loading" data-bind="visible: !hasDiskStatusInfo()">$T('Glitter-loading')<span class="loader-dot-one">.</span><span class="loader-dot-two">.</span><span class="loader-dot-three">.</span></div>
|
||||
</div>
|
||||
|
||||
1435
po/main/da.po
1435
po/main/da.po
File diff suppressed because it is too large
Load Diff
1485
po/main/de.po
1485
po/main/de.po
File diff suppressed because it is too large
Load Diff
1442
po/main/es.po
1442
po/main/es.po
File diff suppressed because it is too large
Load Diff
1437
po/main/fi.po
1437
po/main/fi.po
File diff suppressed because it is too large
Load Diff
1440
po/main/fr.po
1440
po/main/fr.po
File diff suppressed because it is too large
Load Diff
1433
po/main/nb.po
1433
po/main/nb.po
File diff suppressed because it is too large
Load Diff
1442
po/main/nl.po
1442
po/main/nl.po
File diff suppressed because it is too large
Load Diff
1441
po/main/pl.po
1441
po/main/pl.po
File diff suppressed because it is too large
Load Diff
1437
po/main/pt_BR.po
1437
po/main/pt_BR.po
File diff suppressed because it is too large
Load Diff
1437
po/main/ro.po
1437
po/main/ro.po
File diff suppressed because it is too large
Load Diff
1437
po/main/ru.po
1437
po/main/ru.po
File diff suppressed because it is too large
Load Diff
1435
po/main/sr.po
1435
po/main/sr.po
File diff suppressed because it is too large
Load Diff
1435
po/main/sv.po
1435
po/main/sv.po
File diff suppressed because it is too large
Load Diff
1433
po/main/zh_CN.po
1433
po/main/zh_CN.po
File diff suppressed because it is too large
Load Diff
@@ -857,7 +857,7 @@ def keep_awake():
|
||||
def CheckFreeSpace():
|
||||
""" Check if enough disk space is free, if not pause downloader and send email """
|
||||
if cfg.download_free() and not sabnzbd.downloader.Downloader.do.paused:
|
||||
if misc.diskfree(cfg.download_dir.get_path(), force=True) < cfg.download_free.get_float() / GIGI:
|
||||
if misc.diskspace(cfg.download_dir.get_path(), force=True)[1] < cfg.download_free.get_float() / GIGI:
|
||||
logging.warning(T('Too little diskspace forcing PAUSE'))
|
||||
# Pause downloader, but don't save, since the disk is almost full!
|
||||
Downloader.do.pause(save=False)
|
||||
|
||||
@@ -54,7 +54,7 @@ from sabnzbd.utils.json import JsonWriter
|
||||
|
||||
from sabnzbd.utils.rsslib import RSS, Item
|
||||
from sabnzbd.utils.pathbrowser import folders_at_path
|
||||
from sabnzbd.misc import loadavg, to_units, diskfree, disktotal, get_ext, \
|
||||
from sabnzbd.misc import loadavg, to_units, diskspace, get_ext, \
|
||||
get_filename, int_conv, globber, globber_full, time_format, remove_all, \
|
||||
starts_with_path, cat_convert, clip_path, create_https_certificates, calc_age
|
||||
from sabnzbd.encoding import xml_name, unicoder, special_fixer, platform_encode, html_escape
|
||||
@@ -1473,8 +1473,8 @@ def qstatus_data():
|
||||
"noofslots": len(pnfo_list),
|
||||
"noofslots_total": qnfo.q_fullsize,
|
||||
"have_warnings": str(sabnzbd.GUIHANDLER.count()),
|
||||
"diskspace1": diskfree(cfg.download_dir.get_path()),
|
||||
"diskspace2": diskfree(cfg.complete_dir.get_path()),
|
||||
"diskspace1": diskspace(cfg.download_dir.get_path())[1],
|
||||
"diskspace2": diskspace(cfg.complete_dir.get_path())[1],
|
||||
"timeleft": calc_timeleft(qnfo.bytes_left, bpsnow),
|
||||
"loadavg": loadavg(),
|
||||
"speedlimit": "{1:0.{0}f}".format(int(speed_limit % 1 > 0), speed_limit),
|
||||
@@ -1709,16 +1709,16 @@ def build_header(prim, webdir=''):
|
||||
if speed_limit_abs <= 0:
|
||||
speed_limit_abs = ''
|
||||
|
||||
free1 = diskfree(cfg.download_dir.get_path())
|
||||
free2 = diskfree(cfg.complete_dir.get_path())
|
||||
disk_total1, disk_free1 = diskspace(cfg.download_dir.get_path())
|
||||
disk_total2, disk_free2 = diskspace(cfg.complete_dir.get_path())
|
||||
|
||||
header['helpuri'] = 'https://sabnzbd.org/wiki/'
|
||||
header['diskspace1'] = "%.2f" % free1
|
||||
header['diskspace2'] = "%.2f" % free2
|
||||
header['diskspace1_norm'] = to_units(free1 * GIGI)
|
||||
header['diskspace2_norm'] = to_units(free2 * GIGI)
|
||||
header['diskspacetotal1'] = "%.2f" % disktotal(cfg.download_dir.get_path())
|
||||
header['diskspacetotal2'] = "%.2f" % disktotal(cfg.complete_dir.get_path())
|
||||
header['diskspace1'] = "%.2f" % disk_free1
|
||||
header['diskspace2'] = "%.2f" % disk_free2
|
||||
header['diskspace1_norm'] = to_units(disk_free1 * GIGI)
|
||||
header['diskspace2_norm'] = to_units(disk_free2 * GIGI)
|
||||
header['diskspacetotal1'] = "%.2f" % disk_total1
|
||||
header['diskspacetotal2'] = "%.2f" % disk_total2
|
||||
header['loadavg'] = loadavg()
|
||||
# Special formatting so only decimal points when needed
|
||||
header['speedlimit'] = "{1:0.{0}f}".format(int(speed_limit % 1 > 0), speed_limit)
|
||||
|
||||
@@ -317,12 +317,9 @@ def check_encrypted_and_unwanted_files(nzo, filepath):
|
||||
if sabnzbd.WIN32 and has_win_device(filepath):
|
||||
return encrypted, unwanted
|
||||
|
||||
# RarFile requires de-unicoded and clipped filenames for zf.testrar() but not for is_rarfile
|
||||
filepath_rar = deunicode(clip_path(filepath))
|
||||
|
||||
# Is it even a rarfile?
|
||||
if rarfile.is_rarfile(filepath):
|
||||
zf = rarfile.RarFile(filepath_rar, all_names=True)
|
||||
zf = rarfile.RarFile(filepath, all_names=True)
|
||||
|
||||
# Check for encryption
|
||||
if nzo.encrypted == 0 and cfg.pause_on_pwrar() and (zf.needs_password() or is_cloaked(filepath, zf.namelist())):
|
||||
@@ -393,7 +390,7 @@ def check_encrypted_and_unwanted_files(nzo, filepath):
|
||||
zf.close()
|
||||
del zf
|
||||
except:
|
||||
logging.info('Error during inspection of RAR-file %s', filepath_rar, exc_info=True)
|
||||
logging.info('Error during inspection of RAR-file %s', filepath, exc_info=True)
|
||||
|
||||
return encrypted, unwanted
|
||||
|
||||
|
||||
@@ -1163,79 +1163,58 @@ if sabnzbd.WIN32:
|
||||
except:
|
||||
pass
|
||||
|
||||
def diskfree_base(_dir):
|
||||
""" Return amount of free diskspace in GBytes """
|
||||
def diskspace_base(_dir):
|
||||
""" Return amount of free and used diskspace in GBytes """
|
||||
_dir = find_dir(_dir)
|
||||
try:
|
||||
available, disk_size, total_free = win32api.GetDiskFreeSpaceEx(_dir)
|
||||
return available / GIGI
|
||||
return disk_size / GIGI, available / GIGI
|
||||
except:
|
||||
return 0.0
|
||||
return 0.0, 0.0
|
||||
|
||||
def disktotal_base(_dir):
|
||||
""" Return amount of free diskspace in GBytes """
|
||||
_dir = find_dir(_dir)
|
||||
try:
|
||||
available, disk_size, total_free = win32api.GetDiskFreeSpaceEx(_dir)
|
||||
return disk_size / GIGI
|
||||
except:
|
||||
return 0.0
|
||||
else:
|
||||
try:
|
||||
os.statvfs
|
||||
# posix diskfree
|
||||
|
||||
def diskfree_base(_dir):
|
||||
""" Return amount of free diskspace in GBytes """
|
||||
_dir = find_dir(_dir)
|
||||
try:
|
||||
s = os.statvfs(_dir)
|
||||
if s.f_bavail < 0:
|
||||
return float(sys.maxint) * float(s.f_frsize) / GIGI
|
||||
else:
|
||||
return float(s.f_bavail) * float(s.f_frsize) / GIGI
|
||||
except OSError:
|
||||
return 0.0
|
||||
|
||||
def disktotal_base(_dir):
|
||||
""" Return amount of total diskspace in GBytes """
|
||||
def diskspace_base(_dir):
|
||||
""" Return amount of free and used diskspace in GBytes """
|
||||
_dir = find_dir(_dir)
|
||||
try:
|
||||
s = os.statvfs(_dir)
|
||||
if s.f_blocks < 0:
|
||||
return float(sys.maxint) * float(s.f_frsize) / GIGI
|
||||
disk_size = float(sys.maxint) * float(s.f_frsize)
|
||||
else:
|
||||
return float(s.f_blocks) * float(s.f_frsize) / GIGI
|
||||
except OSError:
|
||||
return 0.0
|
||||
disk_size = float(s.f_blocks) * float(s.f_frsize)
|
||||
if s.f_bavail < 0:
|
||||
available = float(sys.maxint) * float(s.f_frsize)
|
||||
else:
|
||||
available = float(s.f_bavail) * float(s.f_frsize)
|
||||
return disk_size / GIGI, available / GIGI
|
||||
except:
|
||||
return 0.0, 0.0
|
||||
except ImportError:
|
||||
def diskfree_base(_dir):
|
||||
return 10.0
|
||||
|
||||
def disktotal_base(_dir):
|
||||
return 20.0
|
||||
def diskspace_base(_dir):
|
||||
return 20.0, 10.0
|
||||
|
||||
|
||||
_LAST_DISK_FREE = 0.0
|
||||
_LAST_DISK_FREE_CALL = 0.0
|
||||
_LAST_DISK_TOTAL = 0.0
|
||||
_LAST_DISK_TOTAL_CALL = 0.0
|
||||
__LAST_DISK_RESULT = {}
|
||||
__LAST_DISK_CALL = {}
|
||||
def diskspace(_dir, force=False):
|
||||
""" Wrapper to cache results """
|
||||
if _dir not in __LAST_DISK_RESULT:
|
||||
__LAST_DISK_RESULT[_dir] = [0.0, 0.0]
|
||||
__LAST_DISK_CALL[_dir] = 0.0
|
||||
|
||||
# Wrappers so we can cache the result, only every 10 seconds
|
||||
def diskfree(_dir, force=False):
|
||||
global _LAST_DISK_FREE_CALL, _LAST_DISK_FREE
|
||||
if force or time.time() > _LAST_DISK_FREE_CALL + 10.0:
|
||||
_LAST_DISK_FREE = diskfree_base(_dir)
|
||||
_LAST_DISK_FREE_CALL = time.time()
|
||||
return _LAST_DISK_FREE
|
||||
# When forced, ignore any cache to avoid problems in UI
|
||||
if force:
|
||||
return diskspace_base(_dir)
|
||||
|
||||
# Check against cache
|
||||
if time.time() > __LAST_DISK_CALL[_dir] + 10.0:
|
||||
__LAST_DISK_RESULT[_dir] = diskspace_base(_dir)
|
||||
__LAST_DISK_CALL[_dir] = time.time()
|
||||
|
||||
def disktotal(_dir, force=False):
|
||||
global _LAST_DISK_TOTAL_CALL, _LAST_DISK_TOTAL
|
||||
if force or time.time() > _LAST_DISK_TOTAL_CALL + 10.0:
|
||||
_LAST_DISK_TOTAL = disktotal_base(_dir)
|
||||
_LAST_DISK_TOTAL_CALL = time.time()
|
||||
return _LAST_DISK_TOTAL
|
||||
return __LAST_DISK_RESULT[_dir]
|
||||
|
||||
|
||||
##############################################################################
|
||||
|
||||
@@ -533,9 +533,9 @@ def rar_extract_core(rarfile_path, numrars, one_folder, nzo, setname, extraction
|
||||
logging.debug("rar_extract(): Extractionpath: %s", extraction_path)
|
||||
|
||||
if password:
|
||||
password = '-p%s' % password
|
||||
password_command = '-p%s' % password
|
||||
else:
|
||||
password = '-p-'
|
||||
password_command = '-p-'
|
||||
|
||||
############################################################################
|
||||
|
||||
@@ -552,15 +552,15 @@ def rar_extract_core(rarfile_path, numrars, one_folder, nzo, setname, extraction
|
||||
if sabnzbd.WIN32:
|
||||
# Use all flags
|
||||
# See: https://github.com/sabnzbd/sabnzbd/pull/771
|
||||
command = ['%s' % RAR_COMMAND, action, '-idp', overwrite, rename, '-ai', password,
|
||||
command = ['%s' % RAR_COMMAND, action, '-idp', overwrite, rename, '-ai', password_command,
|
||||
'%s' % clip_path(rarfile_path), '%s\\' % extraction_path]
|
||||
elif RAR_PROBLEM:
|
||||
# Use only oldest options (specifically no "-or")
|
||||
command = ['%s' % RAR_COMMAND, action, '-idp', overwrite, password,
|
||||
command = ['%s' % RAR_COMMAND, action, '-idp', overwrite, password_command,
|
||||
'%s' % rarfile_path, '%s/' % extraction_path]
|
||||
else:
|
||||
# Don't use "-ai" (not needed for non-Windows)
|
||||
command = ['%s' % RAR_COMMAND, action, '-idp', overwrite, rename, password,
|
||||
command = ['%s' % RAR_COMMAND, action, '-idp', overwrite, rename, password_command,
|
||||
'%s' % rarfile_path, '%s/' % extraction_path]
|
||||
|
||||
if cfg.ignore_unrar_dates():
|
||||
|
||||
@@ -37,7 +37,7 @@ import sabnzbd
|
||||
import sabnzbd.cfg
|
||||
|
||||
from sabnzbd.constants import VALID_ARCHIVES, MEBI, Status
|
||||
from sabnzbd.misc import get_filename, get_ext, diskfree, to_units
|
||||
from sabnzbd.misc import get_filename, get_ext, diskspace, to_units
|
||||
from sabnzbd.panic import launch_a_browser
|
||||
import sabnzbd.notifier as notifier
|
||||
|
||||
@@ -618,8 +618,8 @@ class SABnzbdDelegate(NSObject):
|
||||
|
||||
def diskspaceUpdate(self):
|
||||
try:
|
||||
self.completefolder_menu_item.setTitle_("%s%.2f GB" % (T('Complete Folder') + '\t\t\t', diskfree(sabnzbd.cfg.complete_dir.get_path())))
|
||||
self.incompletefolder_menu_item.setTitle_("%s%.2f GB" % (T('Incomplete Folder') + '\t\t', diskfree(sabnzbd.cfg.download_dir.get_path())))
|
||||
self.completefolder_menu_item.setTitle_("%s%.2f GB" % (T('Complete Folder') + '\t\t\t', diskspace(sabnzbd.cfg.complete_dir.get_path())[1]))
|
||||
self.incompletefolder_menu_item.setTitle_("%s%.2f GB" % (T('Incomplete Folder') + '\t\t', diskspace(sabnzbd.cfg.download_dir.get_path())[1]))
|
||||
except:
|
||||
logging.info("[osx] diskspaceUpdate Exception %s" % (sys.exc_info()[0]))
|
||||
|
||||
|
||||
@@ -468,9 +468,11 @@ def process_job(nzo):
|
||||
script_path = make_script_path(script)
|
||||
if (all_ok or not cfg.safe_postproc()) and (not nzb_list) and script_path:
|
||||
# For windows, we use Short-Paths until 2.0.0 for compatibility
|
||||
if sabnzbd.WIN32 and len(workdir_complete) > 259:
|
||||
if sabnzbd.WIN32:
|
||||
import win32api
|
||||
workdir_complete = win32api.GetShortPathName(workdir_complete)
|
||||
workdir_complete = clip_path(workdir_complete)
|
||||
if len(workdir_complete) > 259:
|
||||
workdir_complete = win32api.GetShortPathName(workdir_complete)
|
||||
|
||||
# set the current nzo status to "Ext Script...". Used in History
|
||||
nzo.status = Status.RUNNING
|
||||
@@ -781,7 +783,7 @@ def try_rar_check(nzo, workdir, setname):
|
||||
# Set path to unrar and open the file
|
||||
# Requires de-unicode for RarFile to work!
|
||||
rarfile.UNRAR_TOOL = sabnzbd.newsunpack.RAR_COMMAND
|
||||
zf = rarfile.RarFile(deunicode(clip_path(rars[0])))
|
||||
zf = rarfile.RarFile(rars[0])
|
||||
|
||||
# Skip if it's encrypted
|
||||
if zf.needs_password():
|
||||
|
||||
@@ -822,10 +822,16 @@ class RarFile(object):
|
||||
def testrar(self):
|
||||
"""Let 'unrar' test the archive.
|
||||
"""
|
||||
# Modified for SABnzbd by clipping paths
|
||||
# and de-unicoding only here
|
||||
from sabnzbd.misc import clip_path
|
||||
from sabnzbd.encoding import deunicode
|
||||
rarpath = deunicode(clip_path(self._rarfile))
|
||||
|
||||
cmd = [UNRAR_TOOL] + list(TEST_ARGS)
|
||||
add_password_arg(cmd, self._password)
|
||||
cmd.append('--')
|
||||
with XTempFile(self._rarfile) as rarfile:
|
||||
with XTempFile(rarpath) as rarfile:
|
||||
cmd.append(rarfile)
|
||||
p = custom_popen(cmd)
|
||||
output = p.communicate()[0]
|
||||
|
||||
Reference in New Issue
Block a user