Fix Utilities.Internal.md5Async() on missing files and empty strings
https://forums.zotero.org/discussion/114208/zotero-7-beta-bug-report-consistent-error-when-syncing
This commit is contained in:
parent
8f2bf50cec
commit
85f58cc97d
2 changed files with 37 additions and 9 deletions
|
@ -139,14 +139,28 @@ Zotero.Utilities.Internal = {
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @param {nsIFile|String} file File or file path
|
* @param {nsIFile|String} file File or file path
|
||||||
* @param {Boolean} [base64=FALSE] Return as base-64-encoded string
|
|
||||||
* rather than hex string
|
|
||||||
*/
|
*/
|
||||||
md5Async: async function (file, base64) {
|
md5Async: async function (file) {
|
||||||
function toHexString(charCode) {
|
function toHexString(charCode) {
|
||||||
return ("0" + charCode.toString(16)).slice(-2);
|
return ("0" + charCode.toString(16)).slice(-2);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
var file = Zotero.File.pathToFile(file);
|
||||||
|
try {
|
||||||
|
let { size } = await IOUtils.stat(file.path);
|
||||||
|
if (size === 0) {
|
||||||
|
// MD5 for empty string
|
||||||
|
return "d41d8cd98f00b204e9800998ecf8427e";
|
||||||
|
}
|
||||||
|
}
|
||||||
|
catch (e) {
|
||||||
|
// Return false for missing files
|
||||||
|
if (e.name == "NotFoundError") {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
throw e;
|
||||||
|
}
|
||||||
|
|
||||||
var ch = Components.classes["@mozilla.org/security/hash;1"]
|
var ch = Components.classes["@mozilla.org/security/hash;1"]
|
||||||
.createInstance(Components.interfaces.nsICryptoHash);
|
.createInstance(Components.interfaces.nsICryptoHash);
|
||||||
ch.init(ch.MD5);
|
ch.init(ch.MD5);
|
||||||
|
@ -156,12 +170,8 @@ Zotero.Utilities.Internal = {
|
||||||
.createInstance(Ci.nsIFileInputStream);
|
.createInstance(Ci.nsIFileInputStream);
|
||||||
is.init(Zotero.File.pathToFile(file), -1, -1, Ci.nsIFileInputStream.CLOSE_ON_EOF);
|
is.init(Zotero.File.pathToFile(file), -1, -1, Ci.nsIFileInputStream.CLOSE_ON_EOF);
|
||||||
ch.updateFromStream(is, -1);
|
ch.updateFromStream(is, -1);
|
||||||
let hash = ch.finish(base64);
|
// Get binary string and convert to hex string
|
||||||
// Base64
|
let hash = ch.finish(false);
|
||||||
if (base64) {
|
|
||||||
return hash;
|
|
||||||
}
|
|
||||||
// Hex string
|
|
||||||
let hexStr = "";
|
let hexStr = "";
|
||||||
for (let i = 0; i < hash.length; i++) {
|
for (let i = 0; i < hash.length; i++) {
|
||||||
hexStr += toHexString(hash.charCodeAt(i));
|
hexStr += toHexString(hash.charCodeAt(i));
|
||||||
|
|
|
@ -44,6 +44,24 @@ describe("Zotero.Utilities.Internal", function () {
|
||||||
|
|
||||||
yield OS.File.remove(file);
|
yield OS.File.remove(file);
|
||||||
});
|
});
|
||||||
|
|
||||||
|
it("should return false for a nonexistent file", async function () {
|
||||||
|
var tmpDir = Zotero.getTempDirectory().path;
|
||||||
|
var file = OS.Path.join(tmpDir, 'nonexistent-asawefaweoihafa');
|
||||||
|
await assert.eventually.isFalse(ZUI.md5Async(file));
|
||||||
|
});
|
||||||
|
|
||||||
|
it("should return hash for an empty file", async function () {
|
||||||
|
const emptyHash = 'd41d8cd98f00b204e9800998ecf8427e';
|
||||||
|
|
||||||
|
var tmpDir = Zotero.getTempDirectory().path;
|
||||||
|
var file = OS.Path.join(tmpDir, 'empty-file');
|
||||||
|
await IOUtils.write(file, new Uint8Array());
|
||||||
|
|
||||||
|
await assert.eventually.equal(ZUI.md5Async(file), emptyHash);
|
||||||
|
|
||||||
|
await IOUtils.remove(file);
|
||||||
|
});
|
||||||
})
|
})
|
||||||
|
|
||||||
|
|
||||||
|
|
Loading…
Reference in a new issue