diff --git a/copyparty/mtag.py b/copyparty/mtag.py index e006b688..8e17a712 100644 --- a/copyparty/mtag.py +++ b/copyparty/mtag.py @@ -131,7 +131,7 @@ class MParser(object): def au_unpk( log: "NamedLogger", fmt_map: dict[str, str], abspath: str, vn: Optional[VFS] = None -) -> str: +) -> Optional[str]: ret = "" maxsz = 1024 * 1024 * 64 try: @@ -178,23 +178,26 @@ def au_unpk( elif pk == "epub": fi = get_cover_from_epub(log, abspath) - assert fi # !rm else: raise Exception("unknown compression %s" % (pk,)) - fsz = 0 - with os.fdopen(fd, "wb") as fo: - while True: - buf = fi.read(32768) - if not buf: - break + if fi: + fsz = 0 + with os.fdopen(fd, "wb") as fo: + while True: + buf = fi.read(32768) + if not buf: + break - fsz += len(buf) - if fsz > maxsz: - raise Exception("zipbomb defused") + fsz += len(buf) + if fsz > maxsz: + raise Exception("zipbomb defused") - fo.write(buf) + fo.write(buf) + else: + wunlink(log, ret, vn.flags if vn else VF_CAREFUL) + return None return ret @@ -422,10 +425,20 @@ def get_cover_from_epub(log: "NamedLogger", abspath: str) -> Optional[IO[bytes]] # This might be an EPUB2 file, try the legacy way of specifying covers coverimage_path = _get_cover_from_epub2(log, package_root, package_ns) - # This url is either absolute (in the .epub) or relative to the package document - adjusted_cover_path = urljoin(rootfile_path, coverimage_path) + if coverimage_path: + # This url is either absolute (in the .epub) or relative to the package document + adjusted_cover_path = urljoin(rootfile_path, coverimage_path) - return z.open(adjusted_cover_path) + try: + return z.open(adjusted_cover_path) + except KeyError: + log( + "epub: cover specified in package document, but doesn't exist: %s" + % (adjusted_cover_path,) + ) + else: + log("epub: no cover found in %s" % (abspath,)) + return None def _get_cover_from_epub2( diff --git a/copyparty/th_srv.py b/copyparty/th_srv.py index 86c3c469..c3ceda02 100644 --- a/copyparty/th_srv.py +++ b/copyparty/th_srv.py @@ -378,6 +378,16 @@ class ThumbSrv(object): if ext in self.args.au_unpk: ap_unpk = au_unpk(self.log, self.args.au_unpk, abspath, vn) + if not ap_unpk: + # This file doesn't have a thumbnail + self.worker_cleanup(abspath, ap_unpk, tpath, None, vn) + try: + # create empty thumbnail, otherwise would try again next time + open(tpath, "ab").close() + except OSError: + pass + continue + else: ap_unpk = abspath @@ -451,40 +461,43 @@ class ThumbSrv(object): except: pass - if abspath != ap_unpk: - wunlink(self.log, ap_unpk, vn.flags) - try: atomic_move(self.log, ttpath, tpath, vn.flags) except Exception as ex: if not os.path.exists(tpath): t = "failed to move [%s] to [%s]: %r" self.log(t % (ttpath, tpath, ex), 3) - pass - untemp = [] - with self.mutex: - subs = self.busy[tpath] - del self.busy[tpath] - self.ram.pop(ttpath, None) - untemp = self.untemp.pop(ttpath, None) or [] - - for ap in untemp: - try: - wunlink(self.log, ap, VF_CAREFUL) - except: - pass - - for x in subs: - with x: - x.notify_all() - - with self.memcond: - self.memcond.notify_all() + self.worker_cleanup(abspath, ap_unpk, tpath, ttpath, vn) with self.mutex: self.nthr -= 1 + def worker_cleanup(self, abspath, ap_unpk, tpath, ttpath, vn): + if abspath != ap_unpk and ap_unpk: + wunlink(self.log, ap_unpk, vn.flags) + + untemp = [] + with self.mutex: + subs = self.busy[tpath] + del self.busy[tpath] + if ttpath: + self.ram.pop(ttpath, None) + untemp = self.untemp.pop(ttpath, None) or [] + + for ap in untemp: + try: + wunlink(self.log, ap, VF_CAREFUL) + except: + pass + + for x in subs: + with x: + x.notify_all() + + with self.memcond: + self.memcond.notify_all() + def fancy_pillow(self, im: "Image.Image", fmt: str, vn: VFS) -> "Image.Image": # exif_transpose is expensive (loads full image + unconditional copy) res = self.getres(vn, fmt) @@ -682,7 +695,7 @@ class ThumbSrv(object): return c: Union[str, int] = "90" - t = "FFmpeg failed (probably a corrupt video file):\n" + t = "FFmpeg failed (probably a corrupt file):\n" if ( (not self.args.th_ff_jpg or time.time() - int(self.args.th_ff_jpg) < 60) and cmd[-1].lower().endswith(b".webp")