Package: mcomix Version: 1.2.1mcomix3+git20190616-1 Severity: critical Tags: patch upstream Justification: causes serious data loss
Dear Maintainer, User bookmarks for the MComix application are stored in a pickle file at ~/.local/share/mcomix/bookmarks.pickle . The Python 3 fork of MComix which Debian has switched to is unable to read this file when it has been written by the earlier, Python 2 version of the application. When this happens, the application prints an error message to the console (which most users will not see since they won't be opening the application from a terminal), and then proceeds to start up. Since no bookmarks have been loaded, when the application saves the current bookmarks back to the file, the contents of the file are reset and the user's existing bookmark collection is destroyed. I reported this problem to upstream, here: https://github.com/multiSnow/mcomix3/issues/98 I also wrote a pull request to fix the problem, here: https://github.com/multiSnow/mcomix3/pull/99 The patch from that PR is attached. The behavior of the application after patching is that now it will be able to read a user bookmarks file produced by the Python 2 version of the applicaton, and if any error is encountered, it will make a backup of the bookmarks pickle file before proceeding, in order to avoid data loss. Thanks, Keshav -- System Information: Debian Release: bullseye/sid APT prefers unstable APT policy: (990, 'unstable') Architecture: amd64 (x86_64) Foreign Architectures: i386 Kernel: Linux 5.3.0-3-amd64 (SMP w/4 CPU cores) Kernel taint flags: TAINT_PROPRIETARY_MODULE, TAINT_OOT_MODULE, TAINT_UNSIGNED_MODULE Locale: LANG=en_US.UTF-8, LC_CTYPE=en_US.UTF-8 (charmap=UTF-8), LANGUAGE= (charmap=UTF-8) Shell: /bin/sh linked to /bin/bash Init: systemd (via /run/systemd/system) Versions of packages mcomix depends on: ii gir1.2-gtk-3.0 3.24.13-1 ii python3 3.7.5-3 ii python3-cairo 1.16.2-2 ii python3-gi 3.34.0-3 ii python3-gi-cairo 3.34.0-3 ii python3-pil 6.2.1-2+b1 Versions of packages mcomix recommends: ii python3-chardet 3.0.4-4 Versions of packages mcomix suggests: pn mupdf-tools <none> ii p7zip 16.02+dfsg-7 ii unrar 1:5.6.6-2 -- no debconf information
>From 8a344788e18a31d34ae1681e1ebe75cd6a02f716 Mon Sep 17 00:00:00 2001 From: Keshav Kini <keshav.k...@gmail.com> Date: Thu, 26 Dec 2019 19:45:23 -0800 Subject: [PATCH] Try to read bookmarks pickled by Python 2 When a pickle file is saved by Python 2, it can be unreadable from Python 3 if certain kinds of objects are stored in it, such as non-Unicode strings. To reliably unpickle these objects, a fallback string encoding must be supplied to `pickle.load()`. It turns out that `datetime` objects, which MComix saves as part of each bookmark, are serialized as non-Unicode binary strings (using the pickle format's opcode `SHORT_BINSTRING`). According to the [Python documentation][1], > Using `encoding='latin1'` is required for unpickling NumPy arrays and > instances of *datetime*, *date* and *time* pickled by Python 2. This commit does as recommended by the above sentence from the documentation. Furthermore, this commit makes it so that if MComix fails to unpickle the bookmarks file, it will back up the existing file before proceeding (because otherwise it will be overwritten with an empty set of bookmarks later). If the backup file cannot be saved, the program will crash to avoid destroying the user's data. [1]: https://docs.python.org/3/library/pickle.html#pickle.Unpickler "pickle" --- mcomix/mcomix/bookmark_backend.py | 12 ++++++++++-- 1 file changed, 10 insertions(+), 2 deletions(-) diff --git a/mcomix/mcomix/bookmark_backend.py b/mcomix/mcomix/bookmark_backend.py index 0492600..8293ee2 100644 --- a/mcomix/mcomix/bookmark_backend.py +++ b/mcomix/mcomix/bookmark_backend.py @@ -6,6 +6,7 @@ from gi.repository import Gtk import operator import datetime import time +import shutil from mcomix import constants from mcomix import log @@ -141,8 +142,8 @@ class __BookmarksStore(object): try: mtime = os.stat(path).st_mtime with open(path, 'rb') as fd: - version = pickle.load(fd) - packs = pickle.load(fd) + version = pickle.load(fd, encoding='latin1') + packs = pickle.load(fd, encoding='latin1') for pack in packs: # Handle old bookmarks without date_added attribute @@ -155,6 +156,13 @@ class __BookmarksStore(object): except Exception: log.error(_('! Could not parse bookmarks file %s'), path) + backup_path = path + '.bak' + if not os.path.exists(backup_path): + log.warning(_('! Backing up bookmarks file to %s'), backup_path) + shutil.copyfile(path, backup_path) + else: + log.error(_('! Cannot create backup bookmarks file at %s'), backup_path) + raise return bookmarks, mtime -- 2.24.1