Add hash check on document read/write (#890)

* Add sha256sum function
* Add hash check to document class
* Make sha256sum test more thorough
* Handle exceptions in the sha256sum function directly
* Update test coverage
* Clarify title on dialog box
* Don't write blank lines in makeAlert
This commit is contained in:
Veronica Berglyd Olsen
2021-09-19 13:55:54 +02:00
committed by GitHub
parent d65c5e93b6
commit c852a5bda3
6 changed files with 140 additions and 29 deletions
+16 -3
View File
@@ -27,7 +27,7 @@ import os
import logging
from novelwriter.enum import nwItemLayout, nwItemClass
from novelwriter.common import isHandle
from novelwriter.common import isHandle, sha256sum
logger = logging.getLogger(__name__)
@@ -44,6 +44,8 @@ class NWDoc():
self._fileLoc = None # The file location of the currently open item
self._docMeta = {} # The meta data of the currently open item
self._docError = "" # The latest encountered IO error
self._prevHash = None # Previous sha256sum of the document file
self._currHash = None # Latest sha256sum of the document file
if isHandle(theHandle):
self._docHandle = theHandle
@@ -80,6 +82,8 @@ class NWDoc():
theText = ""
self._docMeta = {}
self._prevHash = sha256sum(docPath)
if os.path.isfile(docPath):
try:
with open(docPath, mode="r", encoding="utf-8") as inFile:
@@ -108,7 +112,7 @@ class NWDoc():
return theText
def writeDocument(self, docText):
def writeDocument(self, docText, forceWrite=False):
"""Write the document. The file is saved via a temp file in case
of save failure. Returns True if successful, False if not.
"""
@@ -125,7 +129,13 @@ class NWDoc():
docPath = os.path.join(self.theProject.projContent, docFile)
docTemp = os.path.join(self.theProject.projContent, docFile+"~")
# DocMeta line
if self._prevHash is not None and not forceWrite:
self._currHash = sha256sum(docPath)
if self._currHash is not None and self._currHash != self._prevHash:
logger.error("File has been altered on disk since opened")
return False
# DocMeta Line
if self._theItem is None:
docMeta = ""
else:
@@ -149,6 +159,9 @@ class NWDoc():
os.unlink(docPath)
os.rename(docTemp, docPath)
self._prevHash = sha256sum(docPath)
self._currHash = self._prevHash
return True
def deleteDocument(self):