mirror of
https://github.com/kovidgoyal/calibre.git
synced 2025-07-09 03:04:10 -04:00
Edit Book: When downloading external resources, ensure the generated filenames are valid. Fixes #1639448 [download external resorces for dificult url make broken links to files](https://bugs.launchpad.net/calibre/+bug/1639448)
This commit is contained in:
parent
f519b40778
commit
082b1593d6
@ -106,18 +106,23 @@ class NamedEntities(BaseError):
|
|||||||
return changed
|
return changed
|
||||||
|
|
||||||
|
|
||||||
|
def make_filename_safe(name):
|
||||||
|
from calibre.utils.filenames import ascii_filename
|
||||||
|
|
||||||
|
def esc(n):
|
||||||
|
return ''.join(x if x in URL_SAFE else '_' for x in n)
|
||||||
|
return '/'.join(esc(ascii_filename(x)) for x in name.split('/'))
|
||||||
|
|
||||||
|
|
||||||
class EscapedName(BaseError):
|
class EscapedName(BaseError):
|
||||||
|
|
||||||
level = WARN
|
level = WARN
|
||||||
|
|
||||||
def __init__(self, name):
|
def __init__(self, name):
|
||||||
from calibre.utils.filenames import ascii_filename
|
|
||||||
BaseError.__init__(self, _('Filename contains unsafe characters'), name)
|
BaseError.__init__(self, _('Filename contains unsafe characters'), name)
|
||||||
qname = urlquote(name)
|
qname = urlquote(name)
|
||||||
|
|
||||||
def esc(n):
|
self.sname = make_filename_safe(name)
|
||||||
return ''.join(x if x in URL_SAFE else '_' for x in n)
|
|
||||||
self.sname = '/'.join(esc(ascii_filename(x)) for x in name.split('/'))
|
|
||||||
self.HELP = _(
|
self.HELP = _(
|
||||||
'The filename {0} contains unsafe characters, that must be escaped, like'
|
'The filename {0} contains unsafe characters, that must be escaped, like'
|
||||||
' this {1}. This can cause problems with some ebook readers. To be'
|
' this {1}. This can cause problems with some ebook readers. To be'
|
||||||
|
@ -88,6 +88,14 @@ class ProgressTracker(object):
|
|||||||
return ret
|
return ret
|
||||||
|
|
||||||
|
|
||||||
|
def sanitize_file_name(x):
|
||||||
|
from calibre.ebooks.oeb.polish.check.parsing import make_filename_safe
|
||||||
|
x = sanitize_file_name2(x)
|
||||||
|
while '..' in x:
|
||||||
|
x = x.replace('..', '.')
|
||||||
|
return make_filename_safe(x)
|
||||||
|
|
||||||
|
|
||||||
def download_one(tdir, timeout, progress_report, url):
|
def download_one(tdir, timeout, progress_report, url):
|
||||||
try:
|
try:
|
||||||
purl = urlparse(url)
|
purl = urlparse(url)
|
||||||
@ -104,13 +112,13 @@ def download_one(tdir, timeout, progress_report, url):
|
|||||||
dest = ProgressTracker(df, url, sz, progress_report)
|
dest = ProgressTracker(df, url, sz, progress_report)
|
||||||
with closing(src):
|
with closing(src):
|
||||||
shutil.copyfileobj(src, dest)
|
shutil.copyfileobj(src, dest)
|
||||||
filename = sanitize_file_name2(filename)
|
filename = sanitize_file_name(filename)
|
||||||
mt = guess_type(filename)
|
mt = guess_type(filename)
|
||||||
if mt in OEB_DOCS:
|
if mt in OEB_DOCS:
|
||||||
raise ValueError('The external resource {} looks like a HTML document ({})'.format(url, filename))
|
raise ValueError('The external resource {} looks like a HTML document ({})'.format(url, filename))
|
||||||
if not mt or mt == 'application/octet-stream' or '.' not in filename:
|
if not mt or mt == 'application/octet-stream' or '.' not in filename:
|
||||||
raise ValueError('The external resource {} is not of a known type'.format(url))
|
raise ValueError('The external resource {} is not of a known type'.format(url))
|
||||||
return True, (url, sanitize_file_name2(filename), dest.name, mt)
|
return True, (url, filename, dest.name, mt)
|
||||||
except Exception as err:
|
except Exception as err:
|
||||||
return False, (url, as_unicode(err))
|
return False, (url, as_unicode(err))
|
||||||
|
|
||||||
|
@ -12,7 +12,7 @@ def get_download_filename_from_response(response):
|
|||||||
filename = last_part_name = ''
|
filename = last_part_name = ''
|
||||||
try:
|
try:
|
||||||
purl = urlparse(response.geturl())
|
purl = urlparse(response.geturl())
|
||||||
last_part_name = purl.path.split('/')[-1]
|
last_part_name = urllib2_unquote(purl.path.split('/')[-1])
|
||||||
disposition = response.info().get('Content-disposition', '')
|
disposition = response.info().get('Content-disposition', '')
|
||||||
for p in disposition.split(';'):
|
for p in disposition.split(';'):
|
||||||
if 'filename' in p:
|
if 'filename' in p:
|
||||||
@ -58,4 +58,3 @@ def get_download_filename(url, cookie_file=None):
|
|||||||
traceback.print_exc()
|
traceback.print_exc()
|
||||||
|
|
||||||
return filename
|
return filename
|
||||||
|
|
||||||
|
Loading…
x
Reference in New Issue
Block a user