From 4a7f3f5717e8e019bebf82299c86f42ee5ef02d4 Mon Sep 17 00:00:00 2001 From: Charles Haley Date: Tue, 23 Dec 2014 11:31:17 +0100 Subject: [PATCH] Fix problem generating file names in send-to-device and possibly save-to-disk. The original code assumed that the last component always had an extension, which isn't true when evaluating templates to generate a file name. If the resulting string was too long and if last segment of the string contained a period then the remainder of the string after the period was assumed to be an extension. If that remainder was longer than permitted, shorten_components_to generated a path consisting of a single letter. Example: if the template generated this string: "Some of the Best From Tor.com, 2013 Edition_ A Tor.Com Original - A. B. C. Personn & Aa Angstrom & Anne McCaffrey & Banks, Iain M & Bruce Sterling & Cajkovskij, Petr Ilic & Chacko, David & Charlie Huston & Collins, Wilkie & D'Ansey, Leigh & Dahl, Roland & Edward Elmer _Doc_ Smith & Eric Flint & George Charon & Jules Verne (1422)" then the "extension" was everything after the A. B. C., with a length that can easily exceed the max path len. --- src/calibre/devices/smart_device_app/driver.py | 3 ++- src/calibre/devices/utils.py | 2 +- src/calibre/library/save_to_disk.py | 7 ++++--- src/calibre/utils/filenames.py | 4 ++-- 4 files changed, 9 insertions(+), 7 deletions(-) diff --git a/src/calibre/devices/smart_device_app/driver.py b/src/calibre/devices/smart_device_app/driver.py index c9f434fc75..be6f119458 100644 --- a/src/calibre/devices/smart_device_app/driver.py +++ b/src/calibre/devices/smart_device_app/driver.py @@ -453,7 +453,8 @@ class SMART_DEVICE_APP(DeviceConfig, DevicePlugin): app_id = str(getattr(mdata, 'application_id', '')) id_ = mdata.get('id', fname) extra_components = get_components(template, mdata, id_, - timefmt=opts.send_timefmt, length=maxlen-len(app_id)-1) + timefmt=opts.send_timefmt, length=maxlen-len(app_id)-1, + last_has_extension=False) if not extra_components: extra_components.append(sanitize(fname)) else: diff --git a/src/calibre/devices/utils.py b/src/calibre/devices/utils.py index ded1afa8ef..24af74f1a6 100644 --- a/src/calibre/devices/utils.py +++ b/src/calibre/devices/utils.py @@ -100,7 +100,7 @@ def create_upload_path(mdata, fname, template, sanitize, id_ = mdata.get('id', fname) extra_components = get_components(template, mdata, id_, timefmt=opts.send_timefmt, length=maxlen-len(app_id)-1, - sanitize_func=sanitize) + sanitize_func=sanitize, last_has_extension=False) if not extra_components: extra_components.append(sanitize(filename_callback(fname, mdata))) diff --git a/src/calibre/library/save_to_disk.py b/src/calibre/library/save_to_disk.py index d09c222288..247f66e55b 100644 --- a/src/calibre/library/save_to_disk.py +++ b/src/calibre/library/save_to_disk.py @@ -169,7 +169,7 @@ class Formatter(TemplateFormatter): def get_components(template, mi, id, timefmt='%b %Y', length=250, sanitize_func=ascii_filename, replace_whitespace=False, - to_lowercase=False, safe_format=True): + to_lowercase=False, safe_format=True, last_has_extension=True): tsorder = tweaks['save_template_title_series_sorting'] format_args = FORMAT_ARGS.copy() @@ -248,7 +248,7 @@ def get_components(template, mi, id, timefmt='%b %Y', length=250, if replace_whitespace: components = [re.sub(r'\s', '_', x) for x in components] - return shorten_components_to(length, components) + return shorten_components_to(length, components, last_has_extension=last_has_extension) def save_book_to_disk(id_, db, root, opts, length): @@ -286,7 +286,8 @@ def get_path_components(opts, mi, book_id, path_length): components = get_components(opts.template, mi, book_id, opts.timefmt, path_length, ascii_filename if opts.asciiize else sanitize_file_name_unicode, to_lowercase=opts.to_lowercase, - replace_whitespace=opts.replace_whitespace, safe_format=False) + replace_whitespace=opts.replace_whitespace, safe_format=False, + last_has_extension=False) except Exception, e: raise ValueError(_('Failed to calculate path for ' 'save to disk. Template: %(templ)s\n' diff --git a/src/calibre/utils/filenames.py b/src/calibre/utils/filenames.py index 8e50649886..573850584a 100644 --- a/src/calibre/utils/filenames.py +++ b/src/calibre/utils/filenames.py @@ -52,7 +52,7 @@ def shorten_component(s, by_what): return s return s[:l] + s[-l:] -def shorten_components_to(length, components, more_to_take=0): +def shorten_components_to(length, components, more_to_take=0, last_has_extension=True): filepath = os.sep.join(components) extra = len(filepath) - (length - more_to_take) if extra < 1: @@ -68,7 +68,7 @@ def shorten_components_to(length, components, more_to_take=0): if delta > len(x): r = x[0] if x is components[-1] else '' else: - if x is components[-1]: + if last_has_extension and x is components[-1]: b, e = os.path.splitext(x) if e == '.': e = ''