Safer handling of uploaded database files during full sync.
Before overwriting its version of a user's collection database file with one uploaded by the client, the server now performs a basic integrity check using SQLite's 'pragma integrity_check'.
This commit is contained in:
parent
f3788fc2c8
commit
2cb5871ba3
@ -31,6 +31,7 @@ import zipfile
|
|||||||
import ankisyncd
|
import ankisyncd
|
||||||
|
|
||||||
import anki
|
import anki
|
||||||
|
from anki.db import DB
|
||||||
from anki.sync import Syncer, MediaSyncer
|
from anki.sync import Syncer, MediaSyncer
|
||||||
from anki.utils import intTime, checksum, isMac
|
from anki.utils import intTime, checksum, isMac
|
||||||
from anki.consts import SYNC_ZIP_SIZE, SYNC_ZIP_COUNT
|
from anki.consts import SYNC_ZIP_SIZE, SYNC_ZIP_COUNT
|
||||||
@ -405,23 +406,31 @@ class SyncApp(object):
|
|||||||
return data
|
return data
|
||||||
|
|
||||||
def operation_upload(self, col, data, session):
|
def operation_upload(self, col, data, session):
|
||||||
col.close()
|
# Verify integrity of the received database file before replacing our
|
||||||
|
# existing db.
|
||||||
|
temp_db_path = session.get_collection_path() + ".tmp"
|
||||||
|
with open(temp_db_path, 'wb') as f:
|
||||||
|
f.write(data)
|
||||||
|
|
||||||
# TODO: we should verify the database integrity before perminantly overwriting
|
|
||||||
# (ie. use a temporary file) and declaring this a success!
|
|
||||||
#
|
|
||||||
# d = DB(path)
|
|
||||||
# assert d.scalar("pragma integrity_check") == "ok"
|
|
||||||
# d.close()
|
|
||||||
#
|
|
||||||
try:
|
try:
|
||||||
with open(session.get_collection_path(), 'wb') as fd:
|
test_db = DB(temp_db_path)
|
||||||
fd.write(data)
|
if test_db.scalar("pragma integrity_check") != "ok":
|
||||||
|
raise HTTPBadRequest("Integrity check failed for uploaded "
|
||||||
|
"collection database file.")
|
||||||
|
test_db.close()
|
||||||
|
except sqlite.Error as e:
|
||||||
|
raise HTTPBadRequest("Uploaded collection database file is "
|
||||||
|
"corrupt.")
|
||||||
|
|
||||||
|
# Overwrite existing db.
|
||||||
|
col.close()
|
||||||
|
try:
|
||||||
|
os.rename(temp_db_path, session.get_collection_path())
|
||||||
finally:
|
finally:
|
||||||
col.reopen()
|
col.reopen()
|
||||||
col.load()
|
col.load()
|
||||||
|
|
||||||
# run hook_upload if one is defined
|
# If everything went fine, run hook_upload if one is defined.
|
||||||
if self.hook_upload is not None:
|
if self.hook_upload is not None:
|
||||||
self.hook_upload(col, session)
|
self.hook_upload(col, session)
|
||||||
|
|
||||||
|
|||||||
Loading…
Reference in New Issue
Block a user