From f9c2956adabbda480c971cfaf829c35eb538115d Mon Sep 17 00:00:00 2001 From: Kovid Goyal Date: Sun, 9 Nov 2008 12:23:55 -0800 Subject: [PATCH] Implement #1021 (CBR and CBZ cover detection) --- src/calibre/ebooks/metadata/meta.py | 23 +++++++--------- src/calibre/libunrar.py | 42 ++++++++++++++++------------- src/calibre/libunzip.py | 11 ++++---- 3 files changed, 37 insertions(+), 39 deletions(-) diff --git a/src/calibre/ebooks/metadata/meta.py b/src/calibre/ebooks/metadata/meta.py index 266ef99cc2..419b5df167 100644 --- a/src/calibre/ebooks/metadata/meta.py +++ b/src/calibre/ebooks/metadata/meta.py @@ -20,8 +20,8 @@ from calibre.ebooks.metadata.opf import OPFReader from calibre.ebooks.metadata.rtf import set_metadata as set_rtf_metadata from calibre.ebooks.lrf.meta import set_metadata as set_lrf_metadata from calibre.ebooks.metadata.epub import set_metadata as set_epub_metadata -from calibre.libunrar import extract_first as rar_extract_first -from calibre.libunzip import extract_first as zip_extract_first +from calibre.libunrar import extract_member as rar_extract_first +from calibre.libunzip import extract_member as zip_extract_first from calibre.ebooks.metadata import MetaInformation from calibre.ptempfile import TemporaryDirectory @@ -111,18 +111,13 @@ def get_metadata(stream, stream_type='lrf', use_libprs_metadata=False): return base def get_comic_cover(stream, type): - with TemporaryDirectory('_comic_cover') as tdir: - extract_first = zip_extract_first if type == 'zip' else rar_extract_first - extract_first(stream, tdir) - files = os.listdir(tdir) - print tdir, files - if files: - path = os.path.join(tdir, files[0]) - ext = os.path.splitext(path)[1].lower() - if ext: - ext = ext[1:] - return (ext, open(path, 'rb').read()) - + extract_first = zip_extract_first if type == 'zip' else rar_extract_first + ret = extract_first(stream) + if ret is not None: + path, data = ret + ext = os.path.splitext(path)[1][1:] + return (ext.lower(), data) + def set_metadata(stream, mi, stream_type='lrf'): diff --git a/src/calibre/libunrar.py b/src/calibre/libunrar.py index 113ac92e20..bb324282c3 100644 --- a/src/calibre/libunrar.py +++ b/src/calibre/libunrar.py @@ -6,13 +6,14 @@ This module provides a thin ctypes based wrapper around libunrar. See ftp://ftp.rarlabs.com/rar/unrarsrc-3.7.5.tar.gz """ -import os, ctypes, sys +import os, ctypes, sys, re from ctypes import Structure, c_char_p, c_uint, c_void_p, POINTER, \ byref, c_wchar_p, c_int, c_char, c_wchar from tempfile import NamedTemporaryFile from StringIO import StringIO from calibre import iswindows, load_library, CurrentDir +from calibre.ptempfile import TemporaryDirectory _librar_name = 'libunrar' cdll = ctypes.cdll @@ -185,28 +186,31 @@ def extract(path, dir): os.chdir(cwd) _libunrar.RARCloseArchive(arc_data) -def extract_first(path, dir): +def extract_member(path, match=re.compile(r'\.(jpg|jpeg|gif|png)\s*$', re.I)): if hasattr(path, 'read'): data = path.read() f = NamedTemporaryFile(suffix='.rar') f.write(data) f.flush() path = f.name - if not os.path.isdir( dir ): - os.makedirs(dir) - with CurrentDir(dir): - open_archive_data = RAROpenArchiveDataEx(ArcName=path, OpenMode=RAR_OM_EXTRACT, CmtBuf=None) - arc_data = _libunrar.RAROpenArchiveEx(byref(open_archive_data)) - try: - if open_archive_data.OpenResult != 0: - raise UnRARException(_interpret_open_error(open_archive_data.OpenResult, path)) - header_data = RARHeaderDataEx(CmtBuf=None) - if _libunrar.RARReadHeaderEx(arc_data, byref(header_data)) != 0: - raise UnRARException('%s has no files'%path) - PFCode = _libunrar.RARProcessFileW(arc_data, RAR_EXTRACT, None, None) - if PFCode != 0: - raise UnRARException(_interpret_process_file_error(PFCode)) - finally: - _libunrar.RARCloseArchive(arc_data) - + with TemporaryDirectory('_libunrar') as dir: + with CurrentDir(dir): + open_archive_data = RAROpenArchiveDataEx(ArcName=path, OpenMode=RAR_OM_EXTRACT, CmtBuf=None) + arc_data = _libunrar.RAROpenArchiveEx(byref(open_archive_data)) + try: + if open_archive_data.OpenResult != 0: + raise UnRARException(_interpret_open_error(open_archive_data.OpenResult, path)) + header_data = RARHeaderDataEx(CmtBuf=None) + while True: + if _libunrar.RARReadHeaderEx(arc_data, byref(header_data)) != 0: + raise UnRARException('%s has no files'%path) + PFCode = _libunrar.RARProcessFileW(arc_data, RAR_EXTRACT, None, None) + if PFCode != 0: + raise UnRARException(_interpret_process_file_error(PFCode)) + if match.search(header_data.FileNameW): + return header_data.FileNameW.replace('/', os.sep), \ + open(os.path.join(dir, *header_data.FileNameW.split('/')), 'rb').read() + finally: + _libunrar.RARCloseArchive(arc_data) + diff --git a/src/calibre/libunzip.py b/src/calibre/libunzip.py index 1c146c3b1f..6ec5d64313 100644 --- a/src/calibre/libunzip.py +++ b/src/calibre/libunzip.py @@ -3,7 +3,7 @@ __license__ = 'GPL v3' __copyright__ = '2008, Kovid Goyal kovid@kovidgoyal.net' __docformat__ = 'restructuredtext en' -import os +import os, re from calibre.utils import zipfile def update(pathtozip, patterns, filepaths, names, compression=zipfile.ZIP_DEFLATED, verbose=True): @@ -43,10 +43,9 @@ def extract(filename, dir): zf = zipfile.ZipFile( filename ) zf.extractall(dir) -def extract_first(filename, dir): +def extract_member(filename, match=re.compile(r'\.(jpg|jpeg|gif|png)\s*$', re.I)): zf = zipfile.ZipFile(filename) names = zf.namelist() - if not names: - raise ValueError('%s has no files'%filename) - bytes = zf.read(names[0]) - open(os.path.join(dir, names[0]), 'wb').write(bytes) \ No newline at end of file + for name in names: + if match.search(name): + return name, zf.read(name) \ No newline at end of file