From 7eff3815a48d28b3a2965188e593a40f21db2278 Mon Sep 17 00:00:00 2001 From: Karsten Lehmann Date: Fri, 28 Aug 2020 00:34:07 +0200 Subject: [PATCH] Always downgrade the database before sync This prevents the missing collation unicase error on the client --- src/ankisyncd/full_sync.py | 57 ++++++++++++++++++++++++++++++-------- 1 file changed, 46 insertions(+), 11 deletions(-) diff --git a/src/ankisyncd/full_sync.py b/src/ankisyncd/full_sync.py index dd26d68..9e7c3cc 100644 --- a/src/ankisyncd/full_sync.py +++ b/src/ankisyncd/full_sync.py @@ -1,13 +1,36 @@ # -*- coding: utf-8 -*- +import logging import os from sqlite3 import dbapi2 as sqlite +import shutil import sys +from webob.exc import HTTPBadRequest -import anki.db +from anki.db import DB +from anki.collection import Collection -class FullSyncManager: - def upload(self, col, data, session): +logger = logging.getLogger("ankisyncd.media") +logger.setLevel(1) + +class FullSyncManager(object): + def test_db(self, db: DB): + """ + :param anki.db.DB db: the database uploaded from the client. + """ + if db.scalar("pragma integrity_check") != "ok": + raise HTTPBadRequest( + "Integrity check failed for uploaded collection database file." + ) + + def upload(self, col: Collection, data: bytes, session) -> str: + """ + Uploads a sqlite database from the client to the sync server. + + :param anki.collection.Collectio col: + :param bytes data: The binary sqlite database from the client. + :param .sync_app.SyncUserSession session: The current session. + """ # Verify integrity of the received database file before replacing our # existing db. temp_db_path = session.get_collection_path() + ".tmp" @@ -15,10 +38,8 @@ class FullSyncManager: f.write(data) try: - with anki.db.DB(temp_db_path) as test_db: - if test_db.scalar("pragma integrity_check") != "ok": - raise HTTPBadRequest("Integrity check failed for uploaded " - "collection database file.") + with DB(temp_db_path) as test_db: + self.test_db(test_db) except sqlite.Error as e: raise HTTPBadRequest("Uploaded collection database file is " "corrupt.") @@ -26,7 +47,7 @@ class FullSyncManager: # Overwrite existing db. col.close() try: - os.replace(temp_db_path, session.get_collection_path()) + shutil.copyfile(temp_db_path, session.get_collection_path()) finally: col.reopen() # Reopen the media database @@ -34,13 +55,27 @@ class FullSyncManager: return "OK" + def download(self, col: Collection, session) -> bytes: + """Download the binary database. - def download(self, col, session): - col.close() + Performs a downgrade to database schema 11 before sending the database + to the client. + + :param anki.collection.Collection col: + :param .sync_app.SyncUserSession session: + + :return bytes: the binary sqlite3 database + """ + col.close(downgrade=True) + db_path = session.get_collection_path() try: - data = open(session.get_collection_path(), 'rb').read() + with open(db_path, 'rb') as tmp: + data = tmp.read() finally: col.reopen() + # Reopen the media database + col.media.connect() + return data