mirror of
https://github.com/kovidgoyal/calibre.git
synced 2025-07-09 03:04:10 -04:00
Sync to trunk.
This commit is contained in:
commit
bfbcd0fba5
@ -49,6 +49,7 @@ def freeze():
|
|||||||
'/usr/lib/libMagickCore.so',
|
'/usr/lib/libMagickCore.so',
|
||||||
'/usr/lib/libgcrypt.so.11',
|
'/usr/lib/libgcrypt.so.11',
|
||||||
'/usr/lib/libgpg-error.so.0',
|
'/usr/lib/libgpg-error.so.0',
|
||||||
|
'/usr/lib/libphonon.so.4',
|
||||||
]
|
]
|
||||||
|
|
||||||
binary_includes += [os.path.join(QTDIR, 'lib%s.so.4'%x) for x in QTDLLS]
|
binary_includes += [os.path.join(QTDIR, 'lib%s.so.4'%x) for x in QTDLLS]
|
||||||
|
@ -8,7 +8,7 @@ import os
|
|||||||
import shutil
|
import shutil
|
||||||
from itertools import cycle
|
from itertools import cycle
|
||||||
|
|
||||||
from calibre import sanitize_file_name as sanitize
|
from calibre.utils.filenames import ascii_filename as sanitize
|
||||||
from calibre.devices.usbms.driver import USBMS
|
from calibre.devices.usbms.driver import USBMS
|
||||||
import calibre.devices.cybookg3.t2b as t2b
|
import calibre.devices.cybookg3.t2b as t2b
|
||||||
|
|
||||||
@ -98,7 +98,7 @@ class CYBOOKG3(USBMS):
|
|||||||
self.report_progress(i / float(len(files)), _('Transferring books to device...'))
|
self.report_progress(i / float(len(files)), _('Transferring books to device...'))
|
||||||
|
|
||||||
self.report_progress(1.0, _('Transferring books to device...'))
|
self.report_progress(1.0, _('Transferring books to device...'))
|
||||||
|
|
||||||
return zip(paths, cycle([on_card]))
|
return zip(paths, cycle([on_card]))
|
||||||
|
|
||||||
def delete_books(self, paths, end_session=True):
|
def delete_books(self, paths, end_session=True):
|
||||||
|
@ -8,7 +8,7 @@ import os, re, sys, shutil
|
|||||||
from itertools import cycle
|
from itertools import cycle
|
||||||
|
|
||||||
from calibre.devices.usbms.driver import USBMS
|
from calibre.devices.usbms.driver import USBMS
|
||||||
from calibre import sanitize_file_name as sanitize
|
from calibre.utils.filenames import ascii_filename as sanitize
|
||||||
from calibre.ebooks.metadata import string_to_authors
|
from calibre.ebooks.metadata import string_to_authors
|
||||||
|
|
||||||
class JETBOOK(USBMS):
|
class JETBOOK(USBMS):
|
||||||
|
@ -15,7 +15,7 @@ from calibre.devices.interface import DevicePlugin
|
|||||||
from calibre.devices.errors import DeviceError
|
from calibre.devices.errors import DeviceError
|
||||||
from calibre.devices.usbms.deviceconfig import DeviceConfig
|
from calibre.devices.usbms.deviceconfig import DeviceConfig
|
||||||
from calibre import iswindows, islinux, isosx, __appname__
|
from calibre import iswindows, islinux, isosx, __appname__
|
||||||
from calibre import sanitize_file_name as sanitize
|
from calibre.utils.filenames import ascii_filename as sanitize
|
||||||
|
|
||||||
class Device(DeviceConfig, DevicePlugin):
|
class Device(DeviceConfig, DevicePlugin):
|
||||||
'''
|
'''
|
||||||
|
@ -253,7 +253,6 @@ def process_pages(pages, opts, update, tdir):
|
|||||||
|
|
||||||
for job in jobs:
|
for job in jobs:
|
||||||
if job.failed:
|
if job.failed:
|
||||||
raw_input()
|
|
||||||
raise Exception(_('Failed to process comic: \n\n%s')%
|
raise Exception(_('Failed to process comic: \n\n%s')%
|
||||||
job.log_file.read())
|
job.log_file.read())
|
||||||
pages, failures_ = job.result
|
pages, failures_ = job.result
|
||||||
|
@ -18,38 +18,38 @@ from calibre.ebooks.lrf.pylrs.pylrs import Book, PageStyle, TextStyle, \
|
|||||||
from calibre.ebooks.chardet import xml_to_unicode
|
from calibre.ebooks.chardet import xml_to_unicode
|
||||||
|
|
||||||
class LrsParser(object):
|
class LrsParser(object):
|
||||||
|
|
||||||
SELF_CLOSING_TAGS = [i.lower() for i in ['CR', 'Plot', 'NoBR', 'Space',
|
SELF_CLOSING_TAGS = [i.lower() for i in ['CR', 'Plot', 'NoBR', 'Space',
|
||||||
'PutObj', 'RuledLine',
|
'PutObj', 'RuledLine',
|
||||||
'Plot', 'SetDefault', 'BookSetting', 'RegistFont',
|
'Plot', 'SetDefault', 'BookSetting', 'RegistFont',
|
||||||
'PageStyle', 'TextStyle', 'BlockStyle', 'JumpTo',
|
'PageStyle', 'TextStyle', 'BlockStyle', 'JumpTo',
|
||||||
'ImageStream', 'Image']]
|
'ImageStream', 'Image']]
|
||||||
|
|
||||||
def __init__(self, stream, logger):
|
def __init__(self, stream, logger):
|
||||||
self.logger = logger
|
self.logger = logger
|
||||||
src = stream.read()
|
src = stream.read()
|
||||||
self.soup = BeautifulStoneSoup(xml_to_unicode(src)[0],
|
self.soup = BeautifulStoneSoup(xml_to_unicode(src)[0],
|
||||||
convertEntities=BeautifulStoneSoup.XML_ENTITIES,
|
convertEntities=BeautifulStoneSoup.XML_ENTITIES,
|
||||||
selfClosingTags=self.SELF_CLOSING_TAGS)
|
selfClosingTags=self.SELF_CLOSING_TAGS)
|
||||||
self.objects = {}
|
self.objects = {}
|
||||||
for obj in self.soup.findAll(objid=True):
|
for obj in self.soup.findAll(objid=True):
|
||||||
self.objects[obj['objid']] = obj
|
self.objects[obj['objid']] = obj
|
||||||
|
|
||||||
self.parsed_objects = {}
|
self.parsed_objects = {}
|
||||||
self.first_pass()
|
self.first_pass()
|
||||||
self.second_pass()
|
self.second_pass()
|
||||||
self.third_pass()
|
self.third_pass()
|
||||||
self.fourth_pass()
|
self.fourth_pass()
|
||||||
self.fifth_pass()
|
self.fifth_pass()
|
||||||
|
|
||||||
def fifth_pass(self):
|
def fifth_pass(self):
|
||||||
for tag in self.soup.findAll(['canvas', 'header', 'footer']):
|
for tag in self.soup.findAll(['canvas', 'header', 'footer']):
|
||||||
canvas = self.parsed_objects[tag.get('objid')]
|
canvas = self.parsed_objects[tag.get('objid')]
|
||||||
for po in tag.findAll('putobj'):
|
for po in tag.findAll('putobj'):
|
||||||
canvas.put_object(self.parsed_objects[po.get('refobj')],
|
canvas.put_object(self.parsed_objects[po.get('refobj')],
|
||||||
po.get('x1'), po.get('y1'))
|
po.get('x1'), po.get('y1'))
|
||||||
|
|
||||||
|
|
||||||
@classmethod
|
@classmethod
|
||||||
def attrs_to_dict(cls, tag, exclude=('objid',)):
|
def attrs_to_dict(cls, tag, exclude=('objid',)):
|
||||||
result = {}
|
result = {}
|
||||||
@ -58,7 +58,7 @@ class LrsParser(object):
|
|||||||
continue
|
continue
|
||||||
result[str(key)] = val
|
result[str(key)] = val
|
||||||
return result
|
return result
|
||||||
|
|
||||||
def text_tag_to_element(self, tag):
|
def text_tag_to_element(self, tag):
|
||||||
map = {
|
map = {
|
||||||
'span' : Span,
|
'span' : Span,
|
||||||
@ -77,7 +77,7 @@ class LrsParser(object):
|
|||||||
settings = self.attrs_to_dict(tag)
|
settings = self.attrs_to_dict(tag)
|
||||||
settings.pop('spanstyle', '')
|
settings.pop('spanstyle', '')
|
||||||
return map[tag.name](**settings)
|
return map[tag.name](**settings)
|
||||||
|
|
||||||
def process_text_element(self, tag, elem):
|
def process_text_element(self, tag, elem):
|
||||||
for item in tag.contents:
|
for item in tag.contents:
|
||||||
if isinstance(item, NavigableString):
|
if isinstance(item, NavigableString):
|
||||||
@ -86,8 +86,8 @@ class LrsParser(object):
|
|||||||
subelem = self.text_tag_to_element(item)
|
subelem = self.text_tag_to_element(item)
|
||||||
elem.append(subelem)
|
elem.append(subelem)
|
||||||
self.process_text_element(item, subelem)
|
self.process_text_element(item, subelem)
|
||||||
|
|
||||||
|
|
||||||
def process_paragraph(self, tag):
|
def process_paragraph(self, tag):
|
||||||
p = Paragraph()
|
p = Paragraph()
|
||||||
contents = [i for i in tag.contents]
|
contents = [i for i in tag.contents]
|
||||||
@ -104,7 +104,7 @@ class LrsParser(object):
|
|||||||
p.append(elem)
|
p.append(elem)
|
||||||
self.process_text_element(item, elem)
|
self.process_text_element(item, elem)
|
||||||
return p
|
return p
|
||||||
|
|
||||||
def process_text_block(self, tag):
|
def process_text_block(self, tag):
|
||||||
tb = self.parsed_objects[tag.get('objid')]
|
tb = self.parsed_objects[tag.get('objid')]
|
||||||
for item in tag.contents:
|
for item in tag.contents:
|
||||||
@ -119,25 +119,25 @@ class LrsParser(object):
|
|||||||
elem = self.text_tag_to_element(item)
|
elem = self.text_tag_to_element(item)
|
||||||
self.process_text_element(item, elem)
|
self.process_text_element(item, elem)
|
||||||
p.append(elem)
|
p.append(elem)
|
||||||
|
|
||||||
def fourth_pass(self):
|
def fourth_pass(self):
|
||||||
for tag in self.soup.findAll('page'):
|
for tag in self.soup.findAll('page'):
|
||||||
page = self.parsed_objects[tag.get('objid')]
|
page = self.parsed_objects[tag.get('objid')]
|
||||||
self.book.append(page)
|
self.book.append(page)
|
||||||
for block_tag in tag.findAll(['canvas', 'imageblock', 'textblock',
|
for block_tag in tag.findAll(['canvas', 'imageblock', 'textblock',
|
||||||
'ruledline', 'simpletextblock']):
|
'ruledline', 'simpletextblock']):
|
||||||
if block_tag.name == 'ruledline':
|
if block_tag.name == 'ruledline':
|
||||||
page.append(RuledLine(**self.attrs_to_dict(block_tag)))
|
page.append(RuledLine(**self.attrs_to_dict(block_tag)))
|
||||||
else:
|
else:
|
||||||
page.append(self.parsed_objects[block_tag.get('objid')])
|
page.append(self.parsed_objects[block_tag.get('objid')])
|
||||||
|
|
||||||
for tag in self.soup.find('objects').findAll('button'):
|
for tag in self.soup.find('objects').findAll('button'):
|
||||||
jt = tag.find('jumpto')
|
jt = tag.find('jumpto')
|
||||||
tb = self.parsed_objects[jt.get('refobj')]
|
tb = self.parsed_objects[jt.get('refobj')]
|
||||||
jb = JumpButton(tb)
|
jb = JumpButton(tb)
|
||||||
self.book.append(jb)
|
self.book.append(jb)
|
||||||
self.parsed_objects[tag.get('objid')] = jb
|
self.parsed_objects[tag.get('objid')] = jb
|
||||||
|
|
||||||
for tag in self.soup.findAll(['textblock', 'simpletextblock']):
|
for tag in self.soup.findAll(['textblock', 'simpletextblock']):
|
||||||
self.process_text_block(tag)
|
self.process_text_block(tag)
|
||||||
toc = self.soup.find('toc')
|
toc = self.soup.find('toc')
|
||||||
@ -145,11 +145,11 @@ class LrsParser(object):
|
|||||||
for tag in toc.findAll('toclabel'):
|
for tag in toc.findAll('toclabel'):
|
||||||
label = self.tag_to_string(tag)
|
label = self.tag_to_string(tag)
|
||||||
self.book.addTocEntry(label, self.parsed_objects[tag.get('refobj')])
|
self.book.addTocEntry(label, self.parsed_objects[tag.get('refobj')])
|
||||||
|
|
||||||
|
|
||||||
def third_pass(self):
|
def third_pass(self):
|
||||||
map = {
|
map = {
|
||||||
'page' : (Page, ['pagestyle', 'evenfooterid',
|
'page' : (Page, ['pagestyle', 'evenfooterid',
|
||||||
'oddfooterid', 'evenheaderid', 'oddheaderid']),
|
'oddfooterid', 'evenheaderid', 'oddheaderid']),
|
||||||
'textblock' : (TextBlock, ['textstyle', 'blockstyle']),
|
'textblock' : (TextBlock, ['textstyle', 'blockstyle']),
|
||||||
'simpletextblock' : (TextBlock, ['textstyle', 'blockstyle']),
|
'simpletextblock' : (TextBlock, ['textstyle', 'blockstyle']),
|
||||||
@ -167,7 +167,8 @@ class LrsParser(object):
|
|||||||
settings = self.attrs_to_dict(tag, map[tag.name][1]+['objid', 'objlabel'])
|
settings = self.attrs_to_dict(tag, map[tag.name][1]+['objid', 'objlabel'])
|
||||||
for a in ('pagestyle', 'blockstyle', 'textstyle'):
|
for a in ('pagestyle', 'blockstyle', 'textstyle'):
|
||||||
label = tag.get(a, False)
|
label = tag.get(a, False)
|
||||||
if label:
|
if label and \
|
||||||
|
(label in self._style_labels or label in self.parsed_objects):
|
||||||
_obj = self.parsed_objects[label] if \
|
_obj = self.parsed_objects[label] if \
|
||||||
self.parsed_objects.has_key(label) else \
|
self.parsed_objects.has_key(label) else \
|
||||||
self._style_labels[label]
|
self._style_labels[label]
|
||||||
@ -181,9 +182,9 @@ class LrsParser(object):
|
|||||||
if tag.has_key('canvaswidth'):
|
if tag.has_key('canvaswidth'):
|
||||||
args += [tag.get('canvaswidth'), tag.get('canvasheight')]
|
args += [tag.get('canvaswidth'), tag.get('canvasheight')]
|
||||||
self.parsed_objects[id] = map[tag.name][0](*args, **settings)
|
self.parsed_objects[id] = map[tag.name][0](*args, **settings)
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
def second_pass(self):
|
def second_pass(self):
|
||||||
map = {
|
map = {
|
||||||
'pagestyle' : (PageStyle, ['stylelabel', 'evenheaderid', 'oddheaderid', 'evenfooterid', 'oddfooterid']),
|
'pagestyle' : (PageStyle, ['stylelabel', 'evenheaderid', 'oddheaderid', 'evenfooterid', 'oddfooterid']),
|
||||||
@ -207,8 +208,8 @@ class LrsParser(object):
|
|||||||
self._style_labels[x] = self.parsed_objects[id]
|
self._style_labels[x] = self.parsed_objects[id]
|
||||||
if tag.name == 'registfont':
|
if tag.name == 'registfont':
|
||||||
self.book.append(self.parsed_objects[id])
|
self.book.append(self.parsed_objects[id])
|
||||||
|
|
||||||
|
|
||||||
@classmethod
|
@classmethod
|
||||||
def tag_to_string(cls, tag):
|
def tag_to_string(cls, tag):
|
||||||
'''
|
'''
|
||||||
@ -226,20 +227,20 @@ class LrsParser(object):
|
|||||||
res = cls.tag_to_string(item)
|
res = cls.tag_to_string(item)
|
||||||
if res:
|
if res:
|
||||||
strings.append(res)
|
strings.append(res)
|
||||||
return u''.join(strings)
|
return u''.join(strings)
|
||||||
|
|
||||||
def first_pass(self):
|
def first_pass(self):
|
||||||
info = self.soup.find('bbebxylog').find('bookinformation').find('info')
|
info = self.soup.find('bbebxylog').find('bookinformation').find('info')
|
||||||
bookinfo = info.find('bookinfo')
|
bookinfo = info.find('bookinfo')
|
||||||
docinfo = info.find('docinfo')
|
docinfo = info.find('docinfo')
|
||||||
|
|
||||||
def me(base, tagname):
|
def me(base, tagname):
|
||||||
tag = base.find(tagname.lower())
|
tag = base.find(tagname.lower())
|
||||||
if tag is None:
|
if tag is None:
|
||||||
return ('', '', '')
|
return ('', '', '')
|
||||||
tag = (self.tag_to_string(tag), tag.get('reading') if tag.has_key('reading') else '')
|
tag = (self.tag_to_string(tag), tag.get('reading') if tag.has_key('reading') else '')
|
||||||
return tag
|
return tag
|
||||||
|
|
||||||
title = me(bookinfo, 'Title')
|
title = me(bookinfo, 'Title')
|
||||||
author = me(bookinfo, 'Author')
|
author = me(bookinfo, 'Author')
|
||||||
publisher = me(bookinfo, 'Publisher')
|
publisher = me(bookinfo, 'Publisher')
|
||||||
@ -250,12 +251,12 @@ class LrsParser(object):
|
|||||||
creator = me(docinfo, 'Creator')[0]
|
creator = me(docinfo, 'Creator')[0]
|
||||||
producer = me(docinfo, 'Producer')[0]
|
producer = me(docinfo, 'Producer')[0]
|
||||||
bookid = me(bookinfo, 'BookID')[0]
|
bookid = me(bookinfo, 'BookID')[0]
|
||||||
|
|
||||||
sd = self.soup.find('setdefault')
|
sd = self.soup.find('setdefault')
|
||||||
sd = StyleDefault(**self.attrs_to_dict(sd, ['page_tree_id', 'rubyalignandadjust']))
|
sd = StyleDefault(**self.attrs_to_dict(sd, ['page_tree_id', 'rubyalignandadjust']))
|
||||||
bs = self.soup.find('booksetting')
|
bs = self.soup.find('booksetting')
|
||||||
bs = BookSetting(**self.attrs_to_dict(bs, []))
|
bs = BookSetting(**self.attrs_to_dict(bs, []))
|
||||||
|
|
||||||
settings = {}
|
settings = {}
|
||||||
thumbnail = self.soup.find('cthumbnail')
|
thumbnail = self.soup.find('cthumbnail')
|
||||||
if thumbnail is not None:
|
if thumbnail is not None:
|
||||||
@ -264,23 +265,23 @@ class LrsParser(object):
|
|||||||
settings['thumbnail'] = f
|
settings['thumbnail'] = f
|
||||||
else:
|
else:
|
||||||
print _('Could not read from thumbnail file:'), f
|
print _('Could not read from thumbnail file:'), f
|
||||||
|
|
||||||
self.book = Book(title=title, author=author, publisher=publisher,
|
self.book = Book(title=title, author=author, publisher=publisher,
|
||||||
category=category, classification=classification,
|
category=category, classification=classification,
|
||||||
freetext=freetext, language=language, creator=creator,
|
freetext=freetext, language=language, creator=creator,
|
||||||
producer=producer, bookid=bookid, setdefault=sd,
|
producer=producer, bookid=bookid, setdefault=sd,
|
||||||
booksetting=bs, **settings)
|
booksetting=bs, **settings)
|
||||||
|
|
||||||
for hdr in self.soup.findAll(['header', 'footer']):
|
for hdr in self.soup.findAll(['header', 'footer']):
|
||||||
elem = Header if hdr.name == 'header' else Footer
|
elem = Header if hdr.name == 'header' else Footer
|
||||||
self.parsed_objects[hdr.get('objid')] = elem(**self.attrs_to_dict(hdr))
|
self.parsed_objects[hdr.get('objid')] = elem(**self.attrs_to_dict(hdr))
|
||||||
|
|
||||||
def render(self, file, to_lrs=False):
|
def render(self, file, to_lrs=False):
|
||||||
if to_lrs:
|
if to_lrs:
|
||||||
self.book.renderLrs(file, 'utf-8')
|
self.book.renderLrs(file, 'utf-8')
|
||||||
else:
|
else:
|
||||||
self.book.renderLrf(file)
|
self.book.renderLrf(file)
|
||||||
|
|
||||||
|
|
||||||
def option_parser():
|
def option_parser():
|
||||||
parser = OptionParser(usage=_('%prog [options] file.lrs\nCompile an LRS file into an LRF file.'))
|
parser = OptionParser(usage=_('%prog [options] file.lrs\nCompile an LRS file into an LRF file.'))
|
||||||
@ -299,7 +300,7 @@ def main(args=sys.argv, logger=None):
|
|||||||
level = logging.DEBUG if opts.verbose else logging.INFO
|
level = logging.DEBUG if opts.verbose else logging.INFO
|
||||||
logger = logging.getLogger('lrs2lrf')
|
logger = logging.getLogger('lrs2lrf')
|
||||||
setup_cli_handlers(logger, level)
|
setup_cli_handlers(logger, level)
|
||||||
|
|
||||||
if len(args) != 2:
|
if len(args) != 2:
|
||||||
parser.print_help()
|
parser.print_help()
|
||||||
return 1
|
return 1
|
||||||
@ -310,7 +311,7 @@ def main(args=sys.argv, logger=None):
|
|||||||
if opts.verbose:
|
if opts.verbose:
|
||||||
import warnings
|
import warnings
|
||||||
warnings.defaultaction = 'error'
|
warnings.defaultaction = 'error'
|
||||||
|
|
||||||
logger.info('Parsing LRS file...')
|
logger.info('Parsing LRS file...')
|
||||||
converter = LrsParser(open(args[1], 'rb'), logger)
|
converter = LrsParser(open(args[1], 'rb'), logger)
|
||||||
logger.info('Writing to output file...')
|
logger.info('Writing to output file...')
|
||||||
@ -320,4 +321,4 @@ def main(args=sys.argv, logger=None):
|
|||||||
|
|
||||||
|
|
||||||
if __name__ == '__main__':
|
if __name__ == '__main__':
|
||||||
sys.exit(main())
|
sys.exit(main())
|
||||||
|
@ -21,7 +21,8 @@ except ImportError:
|
|||||||
|
|
||||||
from lxml import html, etree
|
from lxml import html, etree
|
||||||
|
|
||||||
from calibre import entity_to_unicode, sanitize_file_name
|
from calibre import entity_to_unicode
|
||||||
|
from calibre.utils.filenames import ascii_filename
|
||||||
from calibre.ptempfile import TemporaryDirectory
|
from calibre.ptempfile import TemporaryDirectory
|
||||||
from calibre.ebooks import DRMError
|
from calibre.ebooks import DRMError
|
||||||
from calibre.ebooks.chardet import ENCODING_PATS
|
from calibre.ebooks.chardet import ENCODING_PATS
|
||||||
@ -374,7 +375,7 @@ class MobiReader(object):
|
|||||||
fname = self.name.encode('ascii', 'replace')
|
fname = self.name.encode('ascii', 'replace')
|
||||||
fname = re.sub(r'[\x08\x15\0]+', '', fname)
|
fname = re.sub(r'[\x08\x15\0]+', '', fname)
|
||||||
htmlfile = os.path.join(output_dir,
|
htmlfile = os.path.join(output_dir,
|
||||||
sanitize_file_name(fname) + '.html')
|
ascii_filename(fname) + '.html')
|
||||||
try:
|
try:
|
||||||
for ref in guide.xpath('descendant::reference'):
|
for ref in guide.xpath('descendant::reference'):
|
||||||
if ref.attrib.has_key('href'):
|
if ref.attrib.has_key('href'):
|
||||||
|
@ -65,9 +65,9 @@ class Jacket(object):
|
|||||||
if not comments.strip():
|
if not comments.strip():
|
||||||
comments = ''
|
comments = ''
|
||||||
comments = comments.replace('\r\n', '\n').replace('\n\n', '<br/><br/>')
|
comments = comments.replace('\r\n', '\n').replace('\n\n', '<br/><br/>')
|
||||||
series = '<b>Series: </b>' + mi.series if mi.series else ''
|
series = '<b>Series: </b>' + escape(mi.series if mi.series else '')
|
||||||
if series and mi.series_index is not None:
|
if series and mi.series_index is not None:
|
||||||
series += ' [%s]'%mi.format_series_index()
|
series += escape(' [%s]'%mi.format_series_index())
|
||||||
tags = mi.tags
|
tags = mi.tags
|
||||||
if not tags:
|
if not tags:
|
||||||
try:
|
try:
|
||||||
@ -75,7 +75,7 @@ class Jacket(object):
|
|||||||
except:
|
except:
|
||||||
tags = []
|
tags = []
|
||||||
if tags:
|
if tags:
|
||||||
tags = '<b>Tags: </b>' + self.opts.dest.tags_to_string(tags)
|
tags = '<b>Tags: </b>' + escape(self.opts.dest.tags_to_string(tags))
|
||||||
else:
|
else:
|
||||||
tags = ''
|
tags = ''
|
||||||
try:
|
try:
|
||||||
@ -84,8 +84,8 @@ class Jacket(object):
|
|||||||
title = _('Unknown')
|
title = _('Unknown')
|
||||||
html = self.JACKET_TEMPLATE%dict(xmlns=XPNSMAP['h'],
|
html = self.JACKET_TEMPLATE%dict(xmlns=XPNSMAP['h'],
|
||||||
title=escape(title), comments=escape(comments),
|
title=escape(title), comments=escape(comments),
|
||||||
jacket=escape(_('Book Jacket')), series=escape(series),
|
jacket=escape(_('Book Jacket')), series=series,
|
||||||
tags=escape(tags))
|
tags=tags)
|
||||||
id, href = self.oeb.manifest.generate('jacket', 'jacket.xhtml')
|
id, href = self.oeb.manifest.generate('jacket', 'jacket.xhtml')
|
||||||
root = etree.fromstring(html)
|
root = etree.fromstring(html)
|
||||||
item = self.oeb.manifest.add(id, href, guess_type(href)[0], data=root)
|
item = self.oeb.manifest.add(id, href, guess_type(href)[0], data=root)
|
||||||
|
@ -57,6 +57,7 @@ it under the same terms as Perl itself.
|
|||||||
import re
|
import re
|
||||||
|
|
||||||
from calibre.ebooks.unidecode.unicodepoints import CODEPOINTS
|
from calibre.ebooks.unidecode.unicodepoints import CODEPOINTS
|
||||||
|
from calibre.constants import preferred_encoding
|
||||||
|
|
||||||
class Unidecoder(object):
|
class Unidecoder(object):
|
||||||
|
|
||||||
@ -70,7 +71,10 @@ class Unidecoder(object):
|
|||||||
try:
|
try:
|
||||||
text = unicode(text)
|
text = unicode(text)
|
||||||
except:
|
except:
|
||||||
text = text.decode('utf-8', 'ignore')
|
try:
|
||||||
|
text = text.decode(preferred_encoding)
|
||||||
|
except:
|
||||||
|
text = text.decode('utf-8', 'replace')
|
||||||
# Replace characters larger than 127 with their ASCII equivelent.
|
# Replace characters larger than 127 with their ASCII equivelent.
|
||||||
return re.sub('[^\x00-\x7f]', lambda x: self.replace_point(x.group()),
|
return re.sub('[^\x00-\x7f]', lambda x: self.replace_point(x.group()),
|
||||||
text)
|
text)
|
||||||
@ -80,7 +84,7 @@ class Unidecoder(object):
|
|||||||
Returns the replacement character or ? if none can be found.
|
Returns the replacement character or ? if none can be found.
|
||||||
'''
|
'''
|
||||||
try:
|
try:
|
||||||
# Splite the unicode character xABCD into parts 0xAB and 0xCD.
|
# Split the unicode character xABCD into parts 0xAB and 0xCD.
|
||||||
# 0xAB represents the group within CODEPOINTS to query and 0xCD
|
# 0xAB represents the group within CODEPOINTS to query and 0xCD
|
||||||
# represents the position in the list of characters for the group.
|
# represents the position in the list of characters for the group.
|
||||||
return CODEPOINTS[self.code_group(codepoint)][self.grouped_point(
|
return CODEPOINTS[self.code_group(codepoint)][self.grouped_point(
|
||||||
|
@ -342,6 +342,8 @@ class FileDialog(QObject):
|
|||||||
ftext += '%s (%s);;'%(text, ' '.join(extensions))
|
ftext += '%s (%s);;'%(text, ' '.join(extensions))
|
||||||
if add_all_files_filter or not ftext:
|
if add_all_files_filter or not ftext:
|
||||||
ftext += 'All files (*)'
|
ftext += 'All files (*)'
|
||||||
|
if ftext.endswith(';;'):
|
||||||
|
ftext = ftext[:-2]
|
||||||
|
|
||||||
self.dialog_name = name if name else 'dialog_' + title
|
self.dialog_name = name if name else 'dialog_' + title
|
||||||
self.selected_files = None
|
self.selected_files = None
|
||||||
|
@ -21,7 +21,7 @@ from calibre.gui2 import config, error_dialog, Dispatcher, dynamic, \
|
|||||||
pixmap_to_data, warning_dialog, \
|
pixmap_to_data, warning_dialog, \
|
||||||
question_dialog
|
question_dialog
|
||||||
from calibre.ebooks.metadata import authors_to_string
|
from calibre.ebooks.metadata import authors_to_string
|
||||||
from calibre import sanitize_file_name, preferred_encoding
|
from calibre import preferred_encoding
|
||||||
from calibre.utils.filenames import ascii_filename
|
from calibre.utils.filenames import ascii_filename
|
||||||
from calibre.devices.errors import FreeSpaceError
|
from calibre.devices.errors import FreeSpaceError
|
||||||
from calibre.utils.smtp import compose_mail, sendmail, extract_email_address, \
|
from calibre.utils.smtp import compose_mail, sendmail, extract_email_address, \
|
||||||
@ -542,7 +542,7 @@ class DeviceGUI(object):
|
|||||||
'\n\n' + t + '\n\t' + _('by') + ' ' + a + '\n\n' + \
|
'\n\n' + t + '\n\t' + _('by') + ' ' + a + '\n\n' + \
|
||||||
_('in the %s format.') %
|
_('in the %s format.') %
|
||||||
os.path.splitext(f)[1][1:].upper())
|
os.path.splitext(f)[1][1:].upper())
|
||||||
prefix = sanitize_file_name(t+' - '+a)
|
prefix = ascii_filename(t+' - '+a)
|
||||||
if not isinstance(prefix, unicode):
|
if not isinstance(prefix, unicode):
|
||||||
prefix = prefix.decode(preferred_encoding, 'replace')
|
prefix = prefix.decode(preferred_encoding, 'replace')
|
||||||
attachment_names.append(prefix + os.path.splitext(f)[1])
|
attachment_names.append(prefix + os.path.splitext(f)[1])
|
||||||
@ -693,7 +693,7 @@ class DeviceGUI(object):
|
|||||||
rows_are_ids=True)
|
rows_are_ids=True)
|
||||||
names = []
|
names = []
|
||||||
for mi in metadata:
|
for mi in metadata:
|
||||||
prefix = sanitize_file_name(mi['title'])
|
prefix = ascii_filename(mi['title'])
|
||||||
if not isinstance(prefix, unicode):
|
if not isinstance(prefix, unicode):
|
||||||
prefix = prefix.decode(preferred_encoding, 'replace')
|
prefix = prefix.decode(preferred_encoding, 'replace')
|
||||||
prefix = ascii_filename(prefix)
|
prefix = ascii_filename(prefix)
|
||||||
@ -758,7 +758,7 @@ class DeviceGUI(object):
|
|||||||
a = mi['authors']
|
a = mi['authors']
|
||||||
if not a:
|
if not a:
|
||||||
a = _('Unknown')
|
a = _('Unknown')
|
||||||
prefix = sanitize_file_name(t+' - '+a)
|
prefix = ascii_filename(t+' - '+a)
|
||||||
if not isinstance(prefix, unicode):
|
if not isinstance(prefix, unicode):
|
||||||
prefix = prefix.decode(preferred_encoding, 'replace')
|
prefix = prefix.decode(preferred_encoding, 'replace')
|
||||||
prefix = ascii_filename(prefix)
|
prefix = ascii_filename(prefix)
|
||||||
|
@ -526,3 +526,11 @@ class MetadataSingleDialog(ResizableDialog, Ui_MetadataSingleDialog):
|
|||||||
QDialog.accept(self)
|
QDialog.accept(self)
|
||||||
if callable(self.accepted_callback):
|
if callable(self.accepted_callback):
|
||||||
self.accepted_callback(self.id)
|
self.accepted_callback(self.id)
|
||||||
|
|
||||||
|
def reject(self, *args):
|
||||||
|
cf = getattr(self, 'cover_fetcher', None)
|
||||||
|
if cf is not None and hasattr(cf, 'terminate'):
|
||||||
|
cf.terminate()
|
||||||
|
cf.wait()
|
||||||
|
|
||||||
|
QDialog.reject(self, *args)
|
||||||
|
@ -14,8 +14,9 @@ from PyQt4.Qt import Qt, SIGNAL, QObject, QCoreApplication, QUrl, QTimer, \
|
|||||||
QMessageBox, QStackedLayout
|
QMessageBox, QStackedLayout
|
||||||
from PyQt4.QtSvg import QSvgRenderer
|
from PyQt4.QtSvg import QSvgRenderer
|
||||||
|
|
||||||
from calibre import __version__, __appname__, sanitize_file_name, \
|
from calibre import __version__, __appname__, \
|
||||||
iswindows, isosx, prints, patheq
|
iswindows, isosx, prints, patheq
|
||||||
|
from calibre.utils.filenames import ascii_filename
|
||||||
from calibre.ptempfile import PersistentTemporaryFile
|
from calibre.ptempfile import PersistentTemporaryFile
|
||||||
from calibre.utils.config import prefs, dynamic
|
from calibre.utils.config import prefs, dynamic
|
||||||
from calibre.utils.ipc.server import Server
|
from calibre.utils.ipc.server import Server
|
||||||
@ -852,7 +853,7 @@ class Main(MainWindow, Ui_MainWindow, DeviceGUI):
|
|||||||
def _files_added(self, paths=[], names=[], infos=[], on_card=None):
|
def _files_added(self, paths=[], names=[], infos=[], on_card=None):
|
||||||
if paths:
|
if paths:
|
||||||
self.upload_books(paths,
|
self.upload_books(paths,
|
||||||
list(map(sanitize_file_name, names)),
|
list(map(ascii_filename, names)),
|
||||||
infos, on_card=on_card)
|
infos, on_card=on_card)
|
||||||
self.status_bar.showMessage(
|
self.status_bar.showMessage(
|
||||||
_('Uploading books to device.'), 2000)
|
_('Uploading books to device.'), 2000)
|
||||||
@ -888,7 +889,17 @@ class Main(MainWindow, Ui_MainWindow, DeviceGUI):
|
|||||||
'removed from your computer. Are you sure?')
|
'removed from your computer. Are you sure?')
|
||||||
+'</p>', 'library_delete_books', self):
|
+'</p>', 'library_delete_books', self):
|
||||||
return
|
return
|
||||||
|
ci = view.currentIndex()
|
||||||
|
row = None
|
||||||
|
if ci.isValid():
|
||||||
|
row = ci.row()
|
||||||
view.model().delete_books(rows)
|
view.model().delete_books(rows)
|
||||||
|
if row is not None:
|
||||||
|
ci = view.model().index(row, 0)
|
||||||
|
if ci.isValid():
|
||||||
|
view.setCurrentIndex(ci)
|
||||||
|
sm = view.selectionModel()
|
||||||
|
sm.select(ci, sm.Select)
|
||||||
else:
|
else:
|
||||||
if self.stack.currentIndex() == 1:
|
if self.stack.currentIndex() == 1:
|
||||||
view = self.memory_view
|
view = self.memory_view
|
||||||
|
@ -34,7 +34,7 @@ from calibre.constants import preferred_encoding, iswindows, isosx, filesystem_e
|
|||||||
from calibre.ptempfile import PersistentTemporaryFile
|
from calibre.ptempfile import PersistentTemporaryFile
|
||||||
from calibre.customize.ui import run_plugins_on_import
|
from calibre.customize.ui import run_plugins_on_import
|
||||||
|
|
||||||
from calibre import sanitize_file_name
|
from calibre.utils.filenames import ascii_filename
|
||||||
from calibre.ebooks import BOOK_EXTENSIONS
|
from calibre.ebooks import BOOK_EXTENSIONS
|
||||||
|
|
||||||
if iswindows:
|
if iswindows:
|
||||||
@ -652,8 +652,8 @@ class LibraryDatabase2(LibraryDatabase):
|
|||||||
authors = self.authors(id, index_is_id=True)
|
authors = self.authors(id, index_is_id=True)
|
||||||
if not authors:
|
if not authors:
|
||||||
authors = _('Unknown')
|
authors = _('Unknown')
|
||||||
author = sanitize_file_name(authors.split(',')[0][:self.PATH_LIMIT]).decode(filesystem_encoding, 'ignore')
|
author = ascii_filename(authors.split(',')[0][:self.PATH_LIMIT]).decode(filesystem_encoding, 'ignore')
|
||||||
title = sanitize_file_name(self.title(id, index_is_id=True)[:self.PATH_LIMIT]).decode(filesystem_encoding, 'ignore')
|
title = ascii_filename(self.title(id, index_is_id=True)[:self.PATH_LIMIT]).decode(filesystem_encoding, 'ignore')
|
||||||
path = author + '/' + title + ' (%d)'%id
|
path = author + '/' + title + ' (%d)'%id
|
||||||
return path
|
return path
|
||||||
|
|
||||||
@ -664,8 +664,8 @@ class LibraryDatabase2(LibraryDatabase):
|
|||||||
authors = self.authors(id, index_is_id=True)
|
authors = self.authors(id, index_is_id=True)
|
||||||
if not authors:
|
if not authors:
|
||||||
authors = _('Unknown')
|
authors = _('Unknown')
|
||||||
author = sanitize_file_name(authors.split(',')[0][:self.PATH_LIMIT]).decode(filesystem_encoding, 'replace')
|
author = ascii_filename(authors.split(',')[0][:self.PATH_LIMIT]).decode(filesystem_encoding, 'replace')
|
||||||
title = sanitize_file_name(self.title(id, index_is_id=True)[:self.PATH_LIMIT]).decode(filesystem_encoding, 'replace')
|
title = ascii_filename(self.title(id, index_is_id=True)[:self.PATH_LIMIT]).decode(filesystem_encoding, 'replace')
|
||||||
name = title + ' - ' + author
|
name = title + ' - ' + author
|
||||||
while name.endswith('.'):
|
while name.endswith('.'):
|
||||||
name = name[:-1]
|
name = name[:-1]
|
||||||
@ -1520,12 +1520,12 @@ class LibraryDatabase2(LibraryDatabase):
|
|||||||
x['cover'] = os.path.join(path, 'cover.jpg')
|
x['cover'] = os.path.join(path, 'cover.jpg')
|
||||||
if not self.has_cover(x['id'], index_is_id=True):
|
if not self.has_cover(x['id'], index_is_id=True):
|
||||||
x['cover'] = None
|
x['cover'] = None
|
||||||
path += os.sep + self.construct_file_name(record[FIELD_MAP['id']]) + '.%s'
|
|
||||||
formats = self.formats(record[FIELD_MAP['id']], index_is_id=True)
|
formats = self.formats(record[FIELD_MAP['id']], index_is_id=True)
|
||||||
if formats:
|
if formats:
|
||||||
for fmt in formats.split(','):
|
for fmt in formats.split(','):
|
||||||
x['formats'].append(path%fmt.lower())
|
path = self.format_abspath(x['id'], fmt, index_is_id=True)
|
||||||
x['fmt_'+fmt.lower()] = path%fmt.lower()
|
x['formats'].append(path)
|
||||||
|
x['fmt_'+fmt.lower()] = path
|
||||||
x['available_formats'] = [i.upper() for i in formats.split(',')]
|
x['available_formats'] = [i.upper() for i in formats.split(',')]
|
||||||
|
|
||||||
return data
|
return data
|
||||||
@ -1602,12 +1602,12 @@ books_series_link feeds
|
|||||||
by_author[au] = []
|
by_author[au] = []
|
||||||
by_author[au].append(index)
|
by_author[au].append(index)
|
||||||
for au in by_author.keys():
|
for au in by_author.keys():
|
||||||
apath = os.path.join(dir, sanitize_file_name(au))
|
apath = os.path.join(dir, ascii_filename(au))
|
||||||
if not single_dir and not os.path.exists(apath):
|
if not single_dir and not os.path.exists(apath):
|
||||||
os.mkdir(apath)
|
os.mkdir(apath)
|
||||||
for idx in by_author[au]:
|
for idx in by_author[au]:
|
||||||
title = re.sub(r'\s', ' ', self.title(idx, index_is_id=index_is_id))
|
title = re.sub(r'\s', ' ', self.title(idx, index_is_id=index_is_id))
|
||||||
tpath = os.path.join(apath, sanitize_file_name(title))
|
tpath = os.path.join(apath, ascii_filename(title))
|
||||||
id = idx if index_is_id else self.id(idx)
|
id = idx if index_is_id else self.id(idx)
|
||||||
id = str(id)
|
id = str(id)
|
||||||
if not single_dir and not os.path.exists(tpath):
|
if not single_dir and not os.path.exists(tpath):
|
||||||
@ -1621,10 +1621,10 @@ books_series_link feeds
|
|||||||
mi.authors = [_('Unknown')]
|
mi.authors = [_('Unknown')]
|
||||||
cdata = self.cover(int(id), index_is_id=True)
|
cdata = self.cover(int(id), index_is_id=True)
|
||||||
if cdata is not None:
|
if cdata is not None:
|
||||||
cname = sanitize_file_name(name)+'.jpg'
|
cname = ascii_filename(name)+'.jpg'
|
||||||
open(os.path.join(base, cname), 'wb').write(cdata)
|
open(os.path.join(base, cname), 'wb').write(cdata)
|
||||||
mi.cover = cname
|
mi.cover = cname
|
||||||
with open(os.path.join(base, sanitize_file_name(name)+'.opf'),
|
with open(os.path.join(base, ascii_filename(name)+'.opf'),
|
||||||
'wb') as f:
|
'wb') as f:
|
||||||
f.write(metadata_to_opf(mi))
|
f.write(metadata_to_opf(mi))
|
||||||
|
|
||||||
@ -1636,7 +1636,7 @@ books_series_link feeds
|
|||||||
if not data:
|
if not data:
|
||||||
continue
|
continue
|
||||||
fname = name +'.'+fmt.lower()
|
fname = name +'.'+fmt.lower()
|
||||||
fname = sanitize_file_name(fname)
|
fname = ascii_filename(fname)
|
||||||
f = open(os.path.join(base, fname), 'w+b')
|
f = open(os.path.join(base, fname), 'w+b')
|
||||||
f.write(data)
|
f.write(data)
|
||||||
f.flush()
|
f.flush()
|
||||||
@ -1671,7 +1671,7 @@ books_series_link feeds
|
|||||||
if not au:
|
if not au:
|
||||||
au = _('Unknown')
|
au = _('Unknown')
|
||||||
fname = '%s - %s.%s'%(title, au, format.lower())
|
fname = '%s - %s.%s'%(title, au, format.lower())
|
||||||
fname = sanitize_file_name(fname)
|
fname = ascii_filename(fname)
|
||||||
if not os.path.exists(dir):
|
if not os.path.exists(dir):
|
||||||
os.makedirs(dir)
|
os.makedirs(dir)
|
||||||
f = open(os.path.join(dir, fname), 'w+b')
|
f = open(os.path.join(dir, fname), 'w+b')
|
||||||
|
@ -82,10 +82,6 @@ sudo python -c "import urllib2; exec urllib2.urlopen('http://calibre.kovidgoyal.
|
|||||||
</pre>
|
</pre>
|
||||||
<h4>Note</h4>
|
<h4>Note</h4>
|
||||||
<ul>
|
<ul>
|
||||||
<li>On some linux distributions, you have to install the
|
|
||||||
libphonon (may be called libphonon4) package for calibre
|
|
||||||
to work.
|
|
||||||
</li>
|
|
||||||
<li>
|
<li>
|
||||||
When running the command line utilities,
|
When running the command line utilities,
|
||||||
they will segfault after completion. This can
|
they will segfault after completion. This can
|
||||||
|
@ -1,97 +1,23 @@
|
|||||||
# -*- coding: utf-8 -*-
|
|
||||||
'''
|
'''
|
||||||
Make strings safe for use as ASCII filenames, while trying to preserve as much
|
Make strings safe for use as ASCII filenames, while trying to preserve as much
|
||||||
meaning as possible.
|
meaning as possible.
|
||||||
'''
|
'''
|
||||||
|
|
||||||
import re, string
|
from calibre.ebooks.unidecode.unidecoder import Unidecoder
|
||||||
|
from calibre import sanitize_file_name
|
||||||
|
from calibre.constants import preferred_encoding
|
||||||
|
udc = Unidecoder()
|
||||||
|
|
||||||
MAP = {
|
def ascii_text(orig):
|
||||||
u"‘" : "'",
|
try:
|
||||||
u"’" : "'",
|
ascii = udc.decode(orig)
|
||||||
u"«" : '"',
|
except:
|
||||||
u"»" : '"',
|
if isinstance(orig, unicode):
|
||||||
u"…" : "...",
|
ascii = orig.encode('ascii', 'replace')
|
||||||
u"№" : "#",
|
ascii = orig.decode(preferred_encoding,
|
||||||
u"Щ" : "Shh",
|
'replace').encode('ascii', 'replace')
|
||||||
u"Ё" : "Jo",
|
return ascii
|
||||||
u"Ж" : "Zh",
|
|
||||||
u"Ц" : "C",
|
|
||||||
u"Ч" : "Ch",
|
|
||||||
u"Ш" : "Sh",
|
|
||||||
u"Ы" : "Y",
|
|
||||||
u"Ю" : "Ju",
|
|
||||||
u"Я" : "Ja",
|
|
||||||
u"Б" : "B",
|
|
||||||
u"Г" : "G",
|
|
||||||
u"Д" : "D",
|
|
||||||
u"И" : "I",
|
|
||||||
u"Й" : "J",
|
|
||||||
u"К" : "K",
|
|
||||||
u"Л" : "L",
|
|
||||||
u"П" : "P",
|
|
||||||
u"Ф" : "F",
|
|
||||||
u"Э" : "E",
|
|
||||||
u"Ъ" : "`",
|
|
||||||
u"Ь" : "'",
|
|
||||||
u"щ" : "shh",
|
|
||||||
u"ё" : "jo",
|
|
||||||
u"ж" : "zh",
|
|
||||||
u"ц" : "c",
|
|
||||||
u"ч" : "ch",
|
|
||||||
u"ш" : "sh",
|
|
||||||
u"ы" : "y",
|
|
||||||
u"ю" : "ju",
|
|
||||||
u"я" : "ja",
|
|
||||||
u"б" : "b",
|
|
||||||
u"в" : "v",
|
|
||||||
u"г" : "g",
|
|
||||||
u"д" : "d",
|
|
||||||
u"з" : "z",
|
|
||||||
u"и" : "i",
|
|
||||||
u"й" : "j",
|
|
||||||
u"к" : "k",
|
|
||||||
u"л" : "l",
|
|
||||||
u"м" : "m",
|
|
||||||
u"н" : "n",
|
|
||||||
u"о" : "o",
|
|
||||||
u"п" : "p",
|
|
||||||
u"т" : "t",
|
|
||||||
u"ф" : "f",
|
|
||||||
u"э" : "e",
|
|
||||||
u"ъ" : "`",
|
|
||||||
u"ь" : "'",
|
|
||||||
u"А" : "A",
|
|
||||||
u"В" : "V",
|
|
||||||
u"Е" : "Je",
|
|
||||||
u"З" : "Z",
|
|
||||||
u"М" : "M",
|
|
||||||
u"Н" : "N",
|
|
||||||
u"О" : "O",
|
|
||||||
u"Р" : "R",
|
|
||||||
u"С" : "S",
|
|
||||||
u"Т" : "T",
|
|
||||||
u"У" : "U",
|
|
||||||
u"Х" : "Kh",
|
|
||||||
u"Є" : "Je",
|
|
||||||
u"Ї" : "Ji",
|
|
||||||
u"а" : "a",
|
|
||||||
u"е" : "je",
|
|
||||||
u"р" : "r",
|
|
||||||
u"с" : "s",
|
|
||||||
u"у" : "u",
|
|
||||||
u"х" : "kh",
|
|
||||||
u"є" : "je",
|
|
||||||
} #: Translation table
|
|
||||||
|
|
||||||
for c in string.whitespace:
|
|
||||||
MAP[c] = ' '
|
|
||||||
PAT = re.compile('['+u''.join(MAP.keys())+']')
|
|
||||||
|
|
||||||
def ascii_filename(orig):
|
def ascii_filename(orig):
|
||||||
orig = PAT.sub(lambda m:MAP[m.group()], orig)
|
return sanitize_file_name(ascii_text(orig).replace('?', '_'))
|
||||||
buf = []
|
|
||||||
for i in range(len(orig)):
|
|
||||||
val = ord(orig[i])
|
|
||||||
buf.append('_' if val < 33 or val > 126 else orig[i])
|
|
||||||
return (''.join(buf)).encode('ascii')
|
|
||||||
|
@ -14,8 +14,8 @@ from httplib import responses
|
|||||||
from PIL import Image
|
from PIL import Image
|
||||||
from cStringIO import StringIO
|
from cStringIO import StringIO
|
||||||
|
|
||||||
from calibre import browser, sanitize_file_name, \
|
from calibre import browser, relpath, unicode_path
|
||||||
relpath, unicode_path
|
from calibre.utils.filenames import ascii_filename
|
||||||
from calibre.ebooks.BeautifulSoup import BeautifulSoup, Tag
|
from calibre.ebooks.BeautifulSoup import BeautifulSoup, Tag
|
||||||
from calibre.ebooks.chardet import xml_to_unicode
|
from calibre.ebooks.chardet import xml_to_unicode
|
||||||
from calibre.utils.config import OptionParser
|
from calibre.utils.config import OptionParser
|
||||||
@ -313,7 +313,7 @@ class RecursiveFetcher(object):
|
|||||||
self.log.exception('Could not fetch image %s'% iurl)
|
self.log.exception('Could not fetch image %s'% iurl)
|
||||||
continue
|
continue
|
||||||
c += 1
|
c += 1
|
||||||
fname = sanitize_file_name('img'+str(c)+ext)
|
fname = ascii_filename('img'+str(c)+ext)
|
||||||
if isinstance(fname, unicode):
|
if isinstance(fname, unicode):
|
||||||
fname = fname.encode('ascii', 'replace')
|
fname = fname.encode('ascii', 'replace')
|
||||||
imgpath = os.path.join(diskpath, fname+'.jpg')
|
imgpath = os.path.join(diskpath, fname+'.jpg')
|
||||||
@ -416,7 +416,7 @@ class RecursiveFetcher(object):
|
|||||||
if not isinstance(_fname, unicode):
|
if not isinstance(_fname, unicode):
|
||||||
_fname.decode('latin1', 'replace')
|
_fname.decode('latin1', 'replace')
|
||||||
_fname = _fname.encode('ascii', 'replace').replace('%', '').replace(os.sep, '')
|
_fname = _fname.encode('ascii', 'replace').replace('%', '').replace(os.sep, '')
|
||||||
_fname = sanitize_file_name(_fname)
|
_fname = ascii_filename(_fname)
|
||||||
_fname = os.path.splitext(_fname)[0]+'.xhtml'
|
_fname = os.path.splitext(_fname)[0]+'.xhtml'
|
||||||
res = os.path.join(linkdiskpath, _fname)
|
res = os.path.join(linkdiskpath, _fname)
|
||||||
self.downloaded_paths.append(res)
|
self.downloaded_paths.append(res)
|
||||||
|
Loading…
x
Reference in New Issue
Block a user