mirror of
https://github.com/kovidgoyal/calibre.git
synced 2025-07-07 10:14:46 -04:00
Handle attempts to convert DRMed files more elegantly
This commit is contained in:
parent
db5d7dc2af
commit
a37d1ecb82
@ -15,6 +15,8 @@ class ConversionError(Exception):
|
|||||||
class UnknownFormatError(Exception):
|
class UnknownFormatError(Exception):
|
||||||
pass
|
pass
|
||||||
|
|
||||||
|
class DRMError(ValueError):
|
||||||
|
pass
|
||||||
|
|
||||||
BOOK_EXTENSIONS = ['lrf', 'rar', 'zip', 'rtf', 'lit', 'txt', 'htm', 'xhtm',
|
BOOK_EXTENSIONS = ['lrf', 'rar', 'zip', 'rtf', 'lit', 'txt', 'htm', 'xhtm',
|
||||||
'html', 'xhtml', 'epub', 'pdf', 'prc', 'mobi', 'azw',
|
'html', 'xhtml', 'epub', 'pdf', 'prc', 'mobi', 'azw',
|
||||||
|
@ -11,6 +11,7 @@ import sys, os, re
|
|||||||
from contextlib import nested
|
from contextlib import nested
|
||||||
|
|
||||||
from calibre import extract, walk
|
from calibre import extract, walk
|
||||||
|
from calibre.ebooks import DRMError
|
||||||
from calibre.ebooks.epub import config as common_config
|
from calibre.ebooks.epub import config as common_config
|
||||||
from calibre.ebooks.epub.from_html import convert as html2epub
|
from calibre.ebooks.epub.from_html import convert as html2epub
|
||||||
from calibre.ptempfile import TemporaryDirectory
|
from calibre.ptempfile import TemporaryDirectory
|
||||||
@ -71,6 +72,9 @@ def pdf2opf(path, tdir, opts):
|
|||||||
def epub2opf(path, tdir, opts):
|
def epub2opf(path, tdir, opts):
|
||||||
zf = ZipFile(path)
|
zf = ZipFile(path)
|
||||||
zf.extractall(tdir)
|
zf.extractall(tdir)
|
||||||
|
print os.listdir(os.path.join(tdir, 'META-INF'))
|
||||||
|
if os.path.exists(os.path.join(tdir, 'META-INF', 'encryption.xml')):
|
||||||
|
raise DRMError(os.path.basename(path))
|
||||||
for f in walk(tdir):
|
for f in walk(tdir):
|
||||||
if f.lower().endswith('.opf'):
|
if f.lower().endswith('.opf'):
|
||||||
return f
|
return f
|
||||||
|
@ -712,7 +712,6 @@ class Processor(Parser):
|
|||||||
for rule in sheet:
|
for rule in sheet:
|
||||||
self.stylesheet.add(rule)
|
self.stylesheet.add(rule)
|
||||||
style.getparent().remove(style)
|
style.getparent().remove(style)
|
||||||
|
|
||||||
cache = {}
|
cache = {}
|
||||||
class_counter = 0
|
class_counter = 0
|
||||||
for font in self.root.xpath('//font'):
|
for font in self.root.xpath('//font'):
|
||||||
@ -753,7 +752,9 @@ class Processor(Parser):
|
|||||||
|
|
||||||
css = '\n'.join(['.%s {%s;}'%(cn, setting) for \
|
css = '\n'.join(['.%s {%s;}'%(cn, setting) for \
|
||||||
setting, cn in cache.items()])
|
setting, cn in cache.items()])
|
||||||
self.stylesheet = self.css_parser.parseString(self.preprocess_css(css))
|
sheet = self.css_parser.parseString(self.preprocess_css(css))
|
||||||
|
for rule in sheet:
|
||||||
|
self.stylesheet.add(rule)
|
||||||
css = ''
|
css = ''
|
||||||
if self.opts.override_css:
|
if self.opts.override_css:
|
||||||
css += '\n\n' + self.opts.override_css
|
css += '\n\n' + self.opts.override_css
|
||||||
|
@ -14,6 +14,7 @@ from lxml import etree
|
|||||||
from calibre.ebooks.lit import LitError
|
from calibre.ebooks.lit import LitError
|
||||||
from calibre.ebooks.lit.maps import OPF_MAP, HTML_MAP
|
from calibre.ebooks.lit.maps import OPF_MAP, HTML_MAP
|
||||||
import calibre.ebooks.lit.mssha1 as mssha1
|
import calibre.ebooks.lit.mssha1 as mssha1
|
||||||
|
from calibre.ebooks import DRMError
|
||||||
from calibre import plugins
|
from calibre import plugins
|
||||||
lzx, lxzerror = plugins['lzx']
|
lzx, lxzerror = plugins['lzx']
|
||||||
msdes, msdeserror = plugins['msdes']
|
msdes, msdeserror = plugins['msdes']
|
||||||
@ -653,7 +654,7 @@ class LitReader(object):
|
|||||||
raise LitError('Unable to decrypt title key!')
|
raise LitError('Unable to decrypt title key!')
|
||||||
self.bookkey = bookkey[1:9]
|
self.bookkey = bookkey[1:9]
|
||||||
else:
|
else:
|
||||||
raise LitError('Cannot extract content from a DRM protected ebook')
|
raise DRMError()
|
||||||
|
|
||||||
def _calculate_deskey(self):
|
def _calculate_deskey(self):
|
||||||
hashfiles = ['/meta', '/DRMStorage/DRMSource']
|
hashfiles = ['/meta', '/DRMStorage/DRMSource']
|
||||||
|
@ -4,7 +4,7 @@ __copyright__ = '2008, Kovid Goyal <kovid at kovidgoyal.net>'
|
|||||||
import os, sys, shutil, logging
|
import os, sys, shutil, logging
|
||||||
from tempfile import mkdtemp
|
from tempfile import mkdtemp
|
||||||
from calibre.ebooks.lrf import option_parser as lrf_option_parser
|
from calibre.ebooks.lrf import option_parser as lrf_option_parser
|
||||||
from calibre.ebooks import ConversionError
|
from calibre.ebooks import ConversionError, DRMError
|
||||||
from calibre.ebooks.lrf.html.convert_from import process_file as html_process_file
|
from calibre.ebooks.lrf.html.convert_from import process_file as html_process_file
|
||||||
from calibre.ebooks.metadata.opf import OPF
|
from calibre.ebooks.metadata.opf import OPF
|
||||||
from calibre.ebooks.metadata.epub import OCFDirReader
|
from calibre.ebooks.metadata.epub import OCFDirReader
|
||||||
@ -27,6 +27,8 @@ def generate_html(pathtoepub, logger):
|
|||||||
os.rmdir(tdir)
|
os.rmdir(tdir)
|
||||||
try:
|
try:
|
||||||
ZipFile(pathtoepub).extractall(tdir)
|
ZipFile(pathtoepub).extractall(tdir)
|
||||||
|
if os.path.exists(os.path.join(tdir, 'META-INF', 'encryption.xml')):
|
||||||
|
raise DRMError(os.path.basename(pathtoepub))
|
||||||
except:
|
except:
|
||||||
if os.path.exists(tdir) and os.path.isdir(tdir):
|
if os.path.exists(tdir) and os.path.isdir(tdir):
|
||||||
shutil.rmtree(tdir)
|
shutil.rmtree(tdir)
|
||||||
|
@ -5,7 +5,7 @@ __copyright__ = '2008, Kovid Goyal <kovid at kovidgoyal.net>'
|
|||||||
import sys, os, subprocess, logging
|
import sys, os, subprocess, logging
|
||||||
from functools import partial
|
from functools import partial
|
||||||
from calibre import isosx, setup_cli_handlers, filename_to_utf8, iswindows, islinux
|
from calibre import isosx, setup_cli_handlers, filename_to_utf8, iswindows, islinux
|
||||||
from calibre.ebooks import ConversionError
|
from calibre.ebooks import ConversionError, DRMError
|
||||||
from calibre.ptempfile import PersistentTemporaryDirectory
|
from calibre.ptempfile import PersistentTemporaryDirectory
|
||||||
from calibre.ebooks.lrf import option_parser as lrf_option_parser
|
from calibre.ebooks.lrf import option_parser as lrf_option_parser
|
||||||
from calibre.ebooks.lrf.html.convert_from import process_file as html_process_file
|
from calibre.ebooks.lrf.html.convert_from import process_file as html_process_file
|
||||||
@ -53,7 +53,7 @@ def generate_html(pathtopdf, tdir):
|
|||||||
err = p.stderr.read()
|
err = p.stderr.read()
|
||||||
raise ConversionError, err
|
raise ConversionError, err
|
||||||
if not os.path.exists(index) or os.stat(index).st_size < 100:
|
if not os.path.exists(index) or os.stat(index).st_size < 100:
|
||||||
raise ConversionError(os.path.basename(pathtopdf) + _(' does not allow copying of text.'), True)
|
raise DRMError()
|
||||||
|
|
||||||
raw = open(index, 'rb').read()
|
raw = open(index, 'rb').read()
|
||||||
open(index, 'wb').write('<!-- created by calibre\'s pdftohtml -->\n'+raw)
|
open(index, 'wb').write('<!-- created by calibre\'s pdftohtml -->\n'+raw)
|
||||||
|
@ -43,8 +43,9 @@ class Container(dict):
|
|||||||
raise EPubException("<rootfile/> element malformed")
|
raise EPubException("<rootfile/> element malformed")
|
||||||
|
|
||||||
class OCF(object):
|
class OCF(object):
|
||||||
MIMETYPE = 'application/epub+zip'
|
MIMETYPE = 'application/epub+zip'
|
||||||
CONTAINER_PATH = 'META-INF/container.xml'
|
CONTAINER_PATH = 'META-INF/container.xml'
|
||||||
|
ENCRYPTION_PATH = 'META-INF/encryption.xml'
|
||||||
|
|
||||||
def __init__(self):
|
def __init__(self):
|
||||||
raise NotImplementedError('Abstract base class')
|
raise NotImplementedError('Abstract base class')
|
||||||
@ -70,6 +71,7 @@ class OCFReader(OCF):
|
|||||||
self.opf = OPF(f, self.root)
|
self.opf = OPF(f, self.root)
|
||||||
except KeyError:
|
except KeyError:
|
||||||
raise EPubException("missing OPF package file")
|
raise EPubException("missing OPF package file")
|
||||||
|
|
||||||
|
|
||||||
class OCFZipReader(OCFReader):
|
class OCFZipReader(OCFReader):
|
||||||
def __init__(self, stream, mode='r', root=None):
|
def __init__(self, stream, mode='r', root=None):
|
||||||
|
@ -123,7 +123,10 @@ class TOC(list):
|
|||||||
path = opfreader.manifest.item(toc.lower())
|
path = opfreader.manifest.item(toc.lower())
|
||||||
path = getattr(path, 'path', path)
|
path = getattr(path, 'path', path)
|
||||||
if path and os.access(path, os.R_OK):
|
if path and os.access(path, os.R_OK):
|
||||||
self.read_ncx_toc(path)
|
try:
|
||||||
|
self.read_ncx_toc(path)
|
||||||
|
except Exception, err:
|
||||||
|
print 'WARNING: Invalid NCX file:', err
|
||||||
return
|
return
|
||||||
cwd = os.path.abspath(self.base_path)
|
cwd = os.path.abspath(self.base_path)
|
||||||
m = glob.glob(os.path.join(cwd, '*.ncx'))
|
m = glob.glob(os.path.join(cwd, '*.ncx'))
|
||||||
|
@ -13,6 +13,7 @@ except ImportError:
|
|||||||
import Image as PILImage
|
import Image as PILImage
|
||||||
|
|
||||||
from calibre import __appname__, entity_to_unicode
|
from calibre import __appname__, entity_to_unicode
|
||||||
|
from calibre.ebooks import DRMError
|
||||||
from calibre.ebooks.BeautifulSoup import BeautifulSoup, Tag
|
from calibre.ebooks.BeautifulSoup import BeautifulSoup, Tag
|
||||||
from calibre.ebooks.mobi import MobiError
|
from calibre.ebooks.mobi import MobiError
|
||||||
from calibre.ebooks.mobi.huffcdic import HuffReader
|
from calibre.ebooks.mobi.huffcdic import HuffReader
|
||||||
@ -165,7 +166,7 @@ class MobiReader(object):
|
|||||||
def extract_content(self, output_dir=os.getcwdu()):
|
def extract_content(self, output_dir=os.getcwdu()):
|
||||||
output_dir = os.path.abspath(output_dir)
|
output_dir = os.path.abspath(output_dir)
|
||||||
if self.book_header.encryption_type != 0:
|
if self.book_header.encryption_type != 0:
|
||||||
raise MobiError('Cannot extract content from a DRM protected ebook')
|
raise DRMError(self.name)
|
||||||
|
|
||||||
processed_records = self.extract_text()
|
processed_records = self.extract_text()
|
||||||
self.add_anchors()
|
self.add_anchors()
|
||||||
|
@ -1117,7 +1117,13 @@ class Main(MainWindow, Ui_MainWindow):
|
|||||||
self.device_error_dialog.show()
|
self.device_error_dialog.show()
|
||||||
|
|
||||||
def job_exception(self, job):
|
def job_exception(self, job):
|
||||||
|
try:
|
||||||
|
if job.exception[0] == 'DRMError':
|
||||||
|
error_dialog(self, _('Conversion Error'),
|
||||||
|
_('<p>Could not convert: %s<p>It is a <a href="http://wiki.mobileread.com/wiki/DRM">DRM</a>ed book. You must first remove the DRM using 3rd party tools.')%job.description.split(':')[-1]).exec_()
|
||||||
|
return
|
||||||
|
except:
|
||||||
|
pass
|
||||||
only_msg = getattr(job.exception, 'only_msg', False)
|
only_msg = getattr(job.exception, 'only_msg', False)
|
||||||
try:
|
try:
|
||||||
print job.console_text()
|
print job.console_text()
|
||||||
|
@ -63,8 +63,6 @@ class TagsModel(QAbstractItemModel):
|
|||||||
def refresh(self):
|
def refresh(self):
|
||||||
old_data = self._data
|
old_data = self._data
|
||||||
self._data = self.db.get_categories(config['sort_by_popularity'])
|
self._data = self.db.get_categories(config['sort_by_popularity'])
|
||||||
for key in self._data:
|
|
||||||
self._data[key] = self._data[key]
|
|
||||||
for key in old_data.keys():
|
for key in old_data.keys():
|
||||||
for tag in old_data[key]:
|
for tag in old_data[key]:
|
||||||
try:
|
try:
|
||||||
|
Loading…
x
Reference in New Issue
Block a user