Add support for EPUB files (#1439)

* Add support for EPUB files

Also generalize open document zip mime detection

* Fix exception handling in MimeFromOpenDocument
This commit is contained in:
Paul Friederichsen 2023-09-23 14:21:26 -05:00 committed by GitHub
parent f8ffeb9074
commit c79355fcc5
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
7 changed files with 43 additions and 31 deletions

View File

@ -746,7 +746,7 @@ class ThumbnailCache( object ):
self._special_thumbs = {}
names = [ 'hydrus', 'pdf', 'psd', 'clip', 'sai', 'krita', 'xcf', 'svg', 'audio', 'video', 'zip' ]
names = [ 'hydrus', 'pdf', 'psd', 'clip', 'sai', 'krita', 'xcf', 'svg', 'audio', 'video', 'zip', 'epub' ]
bounding_dimensions = self._controller.options[ 'thumbnail_dimensions' ]
thumbnail_scale_type = self._controller.new_options.GetInteger( 'thumbnail_scale_type' )
@ -861,6 +861,7 @@ class ThumbnailCache( object ):
elif mime in HC.AUDIO: return self._special_thumbs[ 'audio' ]
elif mime in HC.VIDEO: return self._special_thumbs[ 'video' ]
elif mime == HC.APPLICATION_PDF: return self._special_thumbs[ 'pdf' ]
elif mime == HC.APPLICATION_EPUB: return self._special_thumbs[ 'epub' ]
elif mime == HC.APPLICATION_PSD: return self._special_thumbs[ 'psd' ]
elif mime == HC.APPLICATION_SAI2: return self._special_thumbs[ 'sai' ]
elif mime == HC.APPLICATION_KRITA: return self._special_thumbs[ 'krita' ]

View File

@ -1,5 +1,7 @@
import zipfile
from hydrus.core import HydrusConstants as HC
def ExtractSingleFileFromZip( path_to_zip, filename_to_extract, extract_into_file_path ):
with zipfile.ZipFile( path_to_zip ) as zip_handle:
@ -26,3 +28,18 @@ def ReadSingleFileFromZip( path_to_zip, filename_to_extract ):
def GetZipAsPath( path_to_zip, path_in_zip="" ):
return zipfile.Path( path_to_zip, at=path_in_zip )
def MimeFromOpenDocument( path ):
try:
mimetype_data = GetZipAsPath( path, 'mimetype' ).read_text()
filetype = HC.mime_enum_lookup.get(mimetype_data, None)
return filetype if filetype in HC.OPEN_DOCUMENT_ZIPS else None
except:
return None

View File

@ -730,6 +730,7 @@ UNDETERMINED_GIF = 67
IMAGE_GIF = 68
APPLICATION_PROCREATE = 69
IMAGE_QOI = 70
APPLICATION_EPUB = 71
APPLICATION_OCTET_STREAM = 100
APPLICATION_UNKNOWN = 101
@ -778,6 +779,7 @@ SEARCHABLE_MIMES = {
APPLICATION_XCF,
APPLICATION_PROCREATE,
APPLICATION_PDF,
APPLICATION_EPUB,
APPLICATION_ZIP,
APPLICATION_RAR,
APPLICATION_7Z,
@ -861,7 +863,8 @@ VIDEO = [
APPLICATIONS = [
APPLICATION_FLASH,
APPLICATION_PDF
APPLICATION_PDF,
APPLICATION_EPUB
]
IMAGE_PROJECT_FILES = [
@ -883,6 +886,9 @@ ARCHIVES = [
VIEWABLE_IMAGE_PROJECT_FILES = { APPLICATION_PSD }
# zip files that have a `mimetype` file inside
OPEN_DOCUMENT_ZIPS = { APPLICATION_KRITA, APPLICATION_EPUB }
general_mimetypes_to_mime_groups = {
GENERAL_APPLICATION : APPLICATIONS,
GENERAL_APPLICATION_ARCHIVE : ARCHIVES,
@ -968,6 +974,7 @@ mime_enum_lookup = {
'application/x-yaml' : APPLICATION_YAML,
'PDF document' : APPLICATION_PDF,
'application/pdf' : APPLICATION_PDF,
'application/epub+zip' : APPLICATION_EPUB,
'application/zip' : APPLICATION_ZIP,
'application/vnd.rar' : APPLICATION_RAR,
'application/x-7z-compressed' : APPLICATION_7Z,
@ -1031,6 +1038,7 @@ mime_string_lookup = {
APPLICATION_JSON : 'json',
APPLICATION_CBOR : 'cbor',
APPLICATION_PDF : 'pdf',
APPLICATION_EPUB : 'epub',
APPLICATION_PSD : 'psd',
APPLICATION_CLIP : 'clip',
APPLICATION_SAI2 : 'sai2',
@ -1108,6 +1116,7 @@ mime_mimetype_string_lookup = {
APPLICATION_JSON : 'application/json',
APPLICATION_CBOR : 'application/cbor',
APPLICATION_PDF : 'application/pdf',
APPLICATION_EPUB : 'application/epub+zip',
APPLICATION_PSD : 'image/vnd.adobe.photoshop',
APPLICATION_CLIP : 'application/clip', # made up
APPLICATION_SAI2: 'application/sai2', # made up
@ -1183,6 +1192,7 @@ mime_ext_lookup = {
APPLICATION_YAML : '.yaml',
APPLICATION_JSON : '.json',
APPLICATION_PDF : '.pdf',
APPLICATION_EPUB : '.epub',
APPLICATION_PSD : '.psd',
APPLICATION_CLIP : '.clip',
APPLICATION_SAI2: '.sai2',

View File

@ -5,6 +5,7 @@ from hydrus.core import HydrusAnimationHandling
from hydrus.core import HydrusAudioHandling
from hydrus.core import HydrusPSDHandling
from hydrus.core import HydrusClipHandling
from hydrus.core import HydrusArchiveHandling
from hydrus.core import HydrusConstants as HC
from hydrus.core import HydrusData
from hydrus.core import HydrusDocumentHandling
@ -75,6 +76,8 @@ headers_and_mime.extend( [
( ( ( 42, b'application/x-krita' ), ), HC.APPLICATION_KRITA ), # https://gitlab.freedesktop.org/xdg/shared-mime-info/-/blob/master/data/freedesktop.org.xml.in#L2829
( ( ( 58, b'application/x-krita' ), ), HC.APPLICATION_KRITA ),
( ( ( 63, b'application/x-krita' ), ), HC.APPLICATION_KRITA ),
( ( ( 38, b'application/epub+zip' ), ), HC.APPLICATION_EPUB ),
( ( ( 43, b'application/epub+zip' ), ), HC.APPLICATION_EPUB ),
( ( ( 0, b'PK\x03\x04' ), ), HC.APPLICATION_ZIP ),
( ( ( 0, b'PK\x05\x06' ), ), HC.APPLICATION_ZIP ),
( ( ( 0, b'PK\x07\x08' ), ), HC.APPLICATION_ZIP ),
@ -620,19 +623,18 @@ def GetMime( path, ok_to_look_for_hydrus_updates = False ):
if it_passes:
if mime == HC.APPLICATION_ZIP:
opendoc_mime = HydrusArchiveHandling.MimeFromOpenDocument( path )
if opendoc_mime is not None:
return opendoc_mime
# TODO: since we'll be expanding this to other zip-likes, we should make the zipfile object up here and pass that to various checkers downstream
if HydrusKritaHandling.ZipLooksLikeAKrita( path ):
return HC.APPLICATION_KRITA
elif HydrusProcreateHandling.ZipLooksLikeProcreate( path ):
if HydrusProcreateHandling.ZipLooksLikeProcreate( path ):
return HC.APPLICATION_PROCREATE
else:
return HC.APPLICATION_ZIP
return HC.APPLICATION_ZIP
if mime in ( HC.UNDETERMINED_WM, HC.UNDETERMINED_MP4 ):

View File

@ -6,7 +6,6 @@ import re
KRITA_FILE_THUMB = "preview.png"
KRITA_FILE_MERGED = "mergedimage.png"
KRITA_MIMETYPE = 'mimetype'
def ExtractZippedImageToPath( path_to_zip, temp_path_file ):
@ -63,29 +62,11 @@ def GetKraProperties( path ):
if width is not None and height is not None:
break
except KeyError:
raise HydrusExceptions.NoResolutionFileException( f'This krita file had no {DOCUMENT_INFO_FILE}!' )
return ( width, height )
def ZipLooksLikeAKrita( path ):
try:
mimetype_data = HydrusArchiveHandling.ReadSingleFileFromZip( path, KRITA_MIMETYPE )
return b'application/x-krita' in mimetype_data
except KeyError:
return False

View File

@ -22,6 +22,7 @@ from hydrus.core import HydrusTime
mimes_to_default_thumbnail_paths = collections.defaultdict( lambda: os.path.join( HC.STATIC_DIR, 'hydrus.png' ) )
mimes_to_default_thumbnail_paths[ HC.APPLICATION_PDF ] = os.path.join( HC.STATIC_DIR, 'pdf.png' )
mimes_to_default_thumbnail_paths[ HC.APPLICATION_EPUB ] = os.path.join( HC.STATIC_DIR, 'epub.png' )
mimes_to_default_thumbnail_paths[ HC.APPLICATION_PSD ] = os.path.join( HC.STATIC_DIR, 'psd.png' )
mimes_to_default_thumbnail_paths[ HC.APPLICATION_CLIP ] = os.path.join( HC.STATIC_DIR, 'clip.png' )
mimes_to_default_thumbnail_paths[ HC.APPLICATION_SAI2 ] = os.path.join( HC.STATIC_DIR, 'sai.png' )

BIN
static/epub.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 813 B