mirror of
https://github.com/kovidgoyal/calibre.git
synced 2025-07-08 02:34:06 -04:00
Edit book: When downloading external resources, also convert data URLs into files. Fixes #1774945 [[Enhancement] Image DataURI](https://bugs.launchpad.net/calibre/+bug/1774945)
This commit is contained in:
parent
da35f86fa9
commit
c82ee257dd
@ -2,20 +2,27 @@
|
|||||||
# vim:fileencoding=utf-8
|
# vim:fileencoding=utf-8
|
||||||
# License: GPLv3 Copyright: 2016, Kovid Goyal <kovid at kovidgoyal.net>
|
# License: GPLv3 Copyright: 2016, Kovid Goyal <kovid at kovidgoyal.net>
|
||||||
|
|
||||||
from __future__ import (unicode_literals, division, absolute_import,
|
from __future__ import absolute_import, division, print_function, unicode_literals
|
||||||
print_function)
|
|
||||||
import shutil, os, posixpath, cgi, mimetypes
|
import cgi
|
||||||
|
import mimetypes
|
||||||
|
import os
|
||||||
|
import posixpath
|
||||||
|
import re
|
||||||
|
import shutil
|
||||||
|
from base64 import standard_b64decode
|
||||||
from collections import defaultdict
|
from collections import defaultdict
|
||||||
from contextlib import closing
|
from contextlib import closing
|
||||||
from urlparse import urlparse
|
|
||||||
from multiprocessing.dummy import Pool
|
|
||||||
from functools import partial
|
from functools import partial
|
||||||
|
from io import BytesIO
|
||||||
|
from multiprocessing.dummy import Pool
|
||||||
from tempfile import NamedTemporaryFile
|
from tempfile import NamedTemporaryFile
|
||||||
from urllib2 import urlopen
|
from urllib2 import urlopen
|
||||||
|
from urlparse import urlparse
|
||||||
|
|
||||||
from calibre import as_unicode, sanitize_file_name2
|
from calibre import as_unicode, sanitize_file_name2
|
||||||
|
from calibre.ebooks.oeb.base import OEB_DOCS, OEB_STYLES, barename, iterlinks
|
||||||
from calibre.ebooks.oeb.polish.utils import guess_type
|
from calibre.ebooks.oeb.polish.utils import guess_type
|
||||||
from calibre.ebooks.oeb.base import OEB_DOCS, iterlinks, barename, OEB_STYLES
|
|
||||||
from calibre.ptempfile import TemporaryDirectory
|
from calibre.ptempfile import TemporaryDirectory
|
||||||
from calibre.web import get_download_filename_from_response
|
from calibre.web import get_download_filename_from_response
|
||||||
|
|
||||||
@ -25,7 +32,7 @@ def is_external(url):
|
|||||||
purl = urlparse(url)
|
purl = urlparse(url)
|
||||||
except Exception:
|
except Exception:
|
||||||
return False
|
return False
|
||||||
return purl.scheme in ('http', 'https', 'file', 'ftp')
|
return purl.scheme in ('http', 'https', 'file', 'ftp', 'data')
|
||||||
|
|
||||||
|
|
||||||
def iterhtmllinks(container, name):
|
def iterhtmllinks(container, name):
|
||||||
@ -104,6 +111,24 @@ def download_one(tdir, timeout, progress_report, url):
|
|||||||
src = lopen(purl.path, 'rb')
|
src = lopen(purl.path, 'rb')
|
||||||
filename = os.path.basename(src)
|
filename = os.path.basename(src)
|
||||||
sz = (src.seek(0, os.SEEK_END), src.tell(), src.seek(0))[1]
|
sz = (src.seek(0, os.SEEK_END), src.tell(), src.seek(0))[1]
|
||||||
|
elif purl.scheme == 'data':
|
||||||
|
prefix, payload = purl.path.split(',', 1)
|
||||||
|
parts = prefix.split(';')
|
||||||
|
if parts and parts[-1].lower() == 'base64':
|
||||||
|
payload = re.sub(r'\s+', '', payload)
|
||||||
|
payload = standard_b64decode(payload)
|
||||||
|
else:
|
||||||
|
payload = payload.encode('utf-8')
|
||||||
|
src = BytesIO(payload)
|
||||||
|
sz = len(payload)
|
||||||
|
ext = 'unknown'
|
||||||
|
for x in parts:
|
||||||
|
if '=' not in x and '/' in x:
|
||||||
|
exts = mimetypes.guess_all_extensions(x)
|
||||||
|
if exts:
|
||||||
|
ext = exts[0]
|
||||||
|
break
|
||||||
|
filename = 'data-uri.' + ext
|
||||||
else:
|
else:
|
||||||
src = urlopen(url, timeout=timeout)
|
src = urlopen(url, timeout=timeout)
|
||||||
filename = get_filename(purl, src)
|
filename = get_filename(purl, src)
|
||||||
|
@ -42,14 +42,20 @@ class ChooseResources(QWidget):
|
|||||||
|
|
||||||
@property
|
@property
|
||||||
def resources(self):
|
def resources(self):
|
||||||
return {i.text():self.original_resources[i.text()] for i in self if i.checkState() == Qt.Checked}
|
return {i.data(Qt.UserRole):self.original_resources[i.data(Qt.UserRole)] for i in self if i.checkState() == Qt.Checked}
|
||||||
|
|
||||||
@resources.setter
|
@resources.setter
|
||||||
def resources(self, resources):
|
def resources(self, resources):
|
||||||
self.items.clear()
|
self.items.clear()
|
||||||
self.original_resources = resources
|
self.original_resources = resources
|
||||||
|
dc = 0
|
||||||
for url in resources:
|
for url in resources:
|
||||||
i = QListWidgetItem(url, self.items)
|
text = url
|
||||||
|
if text.startswith('data:'):
|
||||||
|
dc += 1
|
||||||
|
text = _('Data URL ({})').format(dc)
|
||||||
|
i = QListWidgetItem(text, self.items)
|
||||||
|
i.setData(Qt.UserRole, url)
|
||||||
i.setCheckState(Qt.Checked)
|
i.setCheckState(Qt.Checked)
|
||||||
i.setFlags(Qt.ItemIsUserCheckable | Qt.ItemIsEnabled)
|
i.setFlags(Qt.ItemIsUserCheckable | Qt.ItemIsEnabled)
|
||||||
|
|
||||||
|
Loading…
x
Reference in New Issue
Block a user