Changes to item and file retrieval methods

- Zotero.Item.prototype.getFilePath() is now synchronous, with a separate async getFilePathAsync()

- getFile() no longer takes a skipExistsCheck parameter, since that shouldn't happen synchronously

- Zotero.Items.getByLibraryAndKey() is now synchronous again, with a
  separate Zotero.Items.getByLibraryAndKeyAsync() - I haven't fully
  tested this, so I'm not sure if there will need to be any async
  calls.

- Some of the full-text indexing functions now take file paths instead of nsIFile objects

- Zotero.File.getContentsAsync() can now take a string path as well
This commit is contained in:
Dan Stillman 2014-08-07 18:35:12 -04:00
parent e33dc815a0
commit 380668cc60
12 changed files with 248 additions and 89 deletions

View file

@ -120,7 +120,7 @@
var parentKey = this.item.parentKey;
if (parentKey) {
this.parentItem = yield Zotero.Items.getByLibraryAndKey(this.item.libraryID, parentKey);
this.parentItem = Zotero.Items.getByLibraryAndKey(this.item.libraryID, parentKey);
}
this._id('links').item = this.item;

View file

@ -499,7 +499,7 @@ var Zotero_LocateMenu = new function() {
var attachments = item.isAttachment() ? [item] : (yield item.getBestAttachments());
for each(var attachment in attachments) {
if(attachment.attachmentLinkMode !== Zotero.Attachments.LINK_MODE_LINKED_URL) {
var path = yield attachment.getFilePath();
var path = yield attachment.getFilePathAsync();
if (path) {
var ext = Zotero.File.getExtension(Zotero.File.pathToFile(path));
if(!attachment.attachmentMIMEType ||

View file

@ -668,7 +668,7 @@ Zotero.Attachments = new function(){
// We'll index it later if it fails. (This may not be necessary.)
setTimeout(function () {
if (contentType == 'application/pdf') {
Zotero.Fulltext.indexPDF(file, attachmentItem.id);
Zotero.Fulltext.indexPDF(file.path, attachmentItem.id);
}
else if (Zotero.MIME.isTextType(contentType)) {
Zotero.Fulltext.indexDocument(document, attachmentItem.id);
@ -788,7 +788,7 @@ Zotero.Attachments = new function(){
* If a directory exists with the same name, move it to orphaned-files
*
* @param {Number} itemID - Item id
* @return {Promise}
* @return {Promise<nsIFile>}
*/
this.createDirectoryForItem = Zotero.Promise.coroutine(function* (item) {
if (!(item instanceof Zotero.Item)) {

View file

@ -319,7 +319,7 @@ Zotero.Collection.prototype.save = Zotero.Promise.coroutine(function* () {
// Verify parent
if (this._parentKey) {
let newParent = yield Zotero.Collections.getByLibraryAndKey(
let newParent = Zotero.Collections.getByLibraryAndKey(
this.libraryID, this._parentKey
);

View file

@ -105,7 +105,7 @@ Zotero.DataObjects = function (object, objectPlural, id, table) {
let id = ids[i];
// Check if already loaded
if (!this._objectCache[id]) {
throw new Error(this._ZDO_Object + " " + id + " not yet loaded");
throw new this.UnloadedDataException(this._ZDO_Object + " " + id + " not yet loaded");
}
toReturn.push(this._objectCache[id]);
}
@ -215,21 +215,28 @@ Zotero.DataObjects = function (object, objectPlural, id, table) {
* @param {String} key
* @return {Zotero.DataObject} Zotero data object, or FALSE if not found
*/
this.getByLibraryAndKey = Zotero.Promise.coroutine(function* (libraryID, key, options) {
var sql = "SELECT ROWID FROM " + this._ZDO_table + " WHERE ";
if (this._ZDO_idOnly) {
sql += "ROWID=?";
var params = [key]
}
else {
sql += "libraryID=? AND key=?";
var params = [libraryID, key];
}
var id = yield Zotero.DB.valueQueryAsync(sql, params);
this.getByLibraryAndKey = function (libraryID, key, options) {
var id = this.getIDFromLibraryAndKey(libraryID, key);
if (!id) {
return false;
}
return Zotero[this._ZDO_Objects].get(id, options);
};
/**
* Asynchronously retrieves an object by its libraryID and key
*
* @param {Integer} - libraryID
* @param {String} - key
* @return {Promise<Zotero.DataObject>} - Promise for a data object, or FALSE if not found
*/
this.getByLibraryAndKeyAsync = Zotero.Promise.coroutine(function* (libraryID, key, options) {
var id = this.getIDFromLibraryAndKey(libraryID, key);
if (!id) {
return false;
}
return Zotero[this._ZDO_Objects].getAsync(id, options);
});

View file

@ -1356,7 +1356,7 @@ Zotero.Item.prototype.save = Zotero.Promise.coroutine(function* (options) {
// Parent item
let parentItem = this.parentKey;
parentItem = parentItem ? yield Zotero.Items.getByLibraryAndKey(this.libraryID, parentItem) : null;
parentItem = parentItem ? Zotero.Items.getByLibraryAndKey(this.libraryID, parentItem) : null;
if (this._changed.parentKey) {
if (isNew) {
if (!parentItem) {
@ -1394,7 +1394,7 @@ Zotero.Item.prototype.save = Zotero.Promise.coroutine(function* (options) {
var oldParentKey = this._previousData.parentKey;
if (oldParentKey) {
var oldParentItem = yield Zotero.Items.getByLibraryAndKey(this.libraryID, oldParentKey);
var oldParentItem = Zotero.Items.getByLibraryAndKey(this.libraryID, oldParentKey);
if (oldParentItem) {
let oldParentItemNotifierData = {};
//oldParentItemNotifierData[oldParentItem.id] = {};
@ -2088,13 +2088,15 @@ Zotero.Item.prototype.numAttachments = function(includeTrashed) {
/**
* Get an nsILocalFile for the attachment, or false if it doesn't exist
* Get an nsILocalFile for the attachment, or false for invalid paths
*
* This no longer checks whether a file exists
*
* @return {nsILocalFile|false} An nsIFile, or false for invalid paths
*/
Zotero.Item.prototype.getFile = function (skipExistsCheck) {
if (arguments.length > 1) {
Zotero.debug("WARNING: Zotero.Item.prototype.getFile() no longer takes two parameters");
Zotero.Item.prototype.getFile = function () {
if (arguments.length) {
Zotero.debug("WARNING: Zotero.Item.prototype.getFile() no longer takes any arguments");
}
if (!this.isAttachment()) {
@ -2186,21 +2188,17 @@ Zotero.Item.prototype.getFile = function (skipExistsCheck) {
}
}
if (!skipExistsCheck && !file.exists()) {
return false;
}
return file;
};
/**
* Get the absolute file path for the attachment, or false if the associated file doesn't exist
* Get the absolute file path for the attachment
*
* @return {Promise<string|false>} - A promise for either the absolute file path of the attachment
* or false for invalid paths or if the file doesn't exist
* or false for invalid paths
*/
Zotero.Item.prototype.getFilePath = Zotero.Promise.coroutine(function* (skipExistsCheck) {
Zotero.Item.prototype.getFilePath = function () {
if (!this.isAttachment()) {
throw new Error("getFilePath() can only be called on attachment items");
}
@ -2216,7 +2214,137 @@ Zotero.Item.prototype.getFilePath = Zotero.Promise.coroutine(function* (skipExis
if (!path) {
Zotero.debug("Attachment path is empty", 2);
if (!skipExistsCheck) {
yield this._updateAttachmentStates(false);
this._updateAttachmentStates(false);
}
return false;
}
// Imported file with relative path
if (linkMode == Zotero.Attachments.LINK_MODE_IMPORTED_URL ||
linkMode == Zotero.Attachments.LINK_MODE_IMPORTED_FILE) {
try {
if (path.indexOf("storage:") == -1) {
Zotero.debug("Invalid attachment path '" + path + "'", 2);
throw ('Invalid path');
}
// Strip "storage:"
var path = path.substr(8);
// setRelativeDescriptor() silently uses the parent directory on Windows
// if the filename contains certain characters, so strip them —
// but don't skip characters outside of XML range, since they may be
// correct in the opaque relative descriptor string
//
// This is a bad place for this, since the change doesn't make it
// back up to the sync server, but we do it to make sure we don't
// accidentally use the parent dir. Syncing to OS X, which doesn't
// exhibit this bug, will properly correct such filenames in
// storage.js and propagate the change
if (Zotero.isWin) {
path = Zotero.File.getValidFileName(path, true);
}
var file = Zotero.Attachments.getStorageDirectory(this);
file.QueryInterface(Components.interfaces.nsILocalFile);
file.setRelativeDescriptor(file, path);
}
catch (e) {
Zotero.debug(e);
// See if this is a persistent path
// (deprecated for imported attachments)
Zotero.debug('Trying as persistent descriptor');
try {
var file = Components.classes["@mozilla.org/file/local;1"].
createInstance(Components.interfaces.nsILocalFile);
file.persistentDescriptor = path;
// If valid, convert this to a relative descriptor in the background
OS.File.exists(file.path)
.then(function (exists) {
if (exists) {
return Zotero.DB.queryAsync(
"UPDATE itemAttachments SET path=? WHERE itemID=?",
["storage:" + file.leafName, this._id]
);
}
});
}
catch (e) {
Zotero.debug('Invalid persistent descriptor', 2);
this._updateAttachmentStates(false);
return false;
}
}
}
// Linked file with relative path
else if (linkMode == Zotero.Attachments.LINK_MODE_LINKED_FILE &&
path.indexOf(Zotero.Attachments.BASE_PATH_PLACEHOLDER) == 0) {
var file = Zotero.Attachments.resolveRelativePath(path);
if (!file) {
this._updateAttachmentStates(false);
return false;
}
}
else {
var file = Components.classes["@mozilla.org/file/local;1"].
createInstance(Components.interfaces.nsILocalFile);
try {
file.persistentDescriptor = path;
}
catch (e) {
// See if this is an old relative path (deprecated)
Zotero.debug('Invalid persistent descriptor -- trying relative');
try {
var refDir = (linkMode == this.LINK_MODE_LINKED_FILE)
? Zotero.getZoteroDirectory() : Zotero.getStorageDirectory();
file.setRelativeDescriptor(refDir, path);
// If valid, convert this to a persistent descriptor in the background
OS.File.exists(file.path)
.then(function (exists) {
if (exists) {
return Zotero.DB.queryAsync(
"UPDATE itemAttachments SET path=? WHERE itemID=?",
[file.persistentDescriptor, this._id]
);
}
});
}
catch (e) {
Zotero.debug('Invalid relative descriptor', 2);
this._updateAttachmentStates(false);
return false;
}
}
}
return file.path;
};
/**
* Get the absolute path for the attachment, if it exists
*
* @return {Promise<String|false>} - A promise for either the absolute path of the attachment
* or false for invalid paths or if the file doesn't exist
*/
Zotero.Item.prototype.getFilePathAsync = Zotero.Promise.coroutine(function* (skipExistsCheck) {
if (!this.isAttachment()) {
throw new Error("getFilePathAsync() can only be called on attachment items");
}
var linkMode = this.attachmentLinkMode;
var path = this.attachmentPath;
// No associated files for linked URLs
if (linkMode == Zotero.Attachments.LINK_MODE_LINKED_URL) {
return false;
}
if (!path) {
Zotero.debug("Attachment path is empty", 2);
if (!skipExistsCheck) {
this._updateAttachmentStates(false);
}
return false;
}
@ -2269,7 +2397,7 @@ Zotero.Item.prototype.getFilePath = Zotero.Promise.coroutine(function* (skipExis
catch (e) {
Zotero.debug('Invalid persistent descriptor', 2);
if (!skipExistsCheck) {
yield this._updateAttachmentStates(false);
this._updateAttachmentStates(false);
}
return false;
}
@ -2280,7 +2408,7 @@ Zotero.Item.prototype.getFilePath = Zotero.Promise.coroutine(function* (skipExis
path.indexOf(Zotero.Attachments.BASE_PATH_PLACEHOLDER) == 0) {
var file = Zotero.Attachments.resolveRelativePath(path);
if (!skipExistsCheck && !file) {
yield this._updateAttachmentStates(false);
this._updateAttachmentStates(false);
return false;
}
}
@ -2307,32 +2435,33 @@ Zotero.Item.prototype.getFilePath = Zotero.Promise.coroutine(function* (skipExis
catch (e) {
Zotero.debug('Invalid relative descriptor', 2);
if (!skipExistsCheck) {
yield this._updateAttachmentStates(false);
this._updateAttachmentStates(false);
}
return false;
}
}
}
path = file.path;
var path = file.path;
if (!skipExistsCheck && !(yield OS.File.exists(path))) {
Zotero.debug("Attachment file '" + path + "' not found", 2);
yield this._updateAttachmentStates(false);
this._updateAttachmentStates(false);
return false;
}
if (!skipExistsCheck) {
yield this._updateAttachmentStates(true);
this._updateAttachmentStates(true);
}
return path;
return file.path;
});
/**
* Update file existence state of this item and best attachment state of parent item
*/
Zotero.Item.prototype._updateAttachmentStates = Zotero.Promise.coroutine(function* (exists) {
Zotero.Item.prototype._updateAttachmentStates = function (exists) {
this._fileExists = exists;
if (this.isTopLevelItem()) {
@ -2351,9 +2480,18 @@ Zotero.Item.prototype._updateAttachmentStates = Zotero.Promise.coroutine(functio
return;
}
var item = yield Zotero.Items.getByLibraryAndKey(this.libraryID, parentKey);
try {
var item = Zotero.Items.getByLibraryAndKey(this.libraryID, parentKey);
}
catch (e) {
if (e instanceof Zotero.Items.UnloadedDataException) {
Zotero.debug("Attachment parent not yet loaded in Zotero.Item.updateAttachmentStates()", 2);
return;
}
throw e;
}
item.clearBestAttachmentState();
});
};
Zotero.Item.prototype.getFilename = function () {
@ -2366,7 +2504,6 @@ Zotero.Item.prototype.getFilename = function () {
}
var file = this.getFile();
// Invalid path
if (!file) {
return '';
}
@ -2377,7 +2514,7 @@ Zotero.Item.prototype.getFilename = function () {
/**
* Asynchronous cached check for file existence, used for items view
*
* This is updated only initially and on subsequent getFilePath() calls.
* This is updated only initially and on subsequent getFilePathAsync() calls.
*/
Zotero.Item.prototype.fileExists = Zotero.Promise.coroutine(function* () {
if (this._fileExists !== null) {
@ -2392,9 +2529,7 @@ Zotero.Item.prototype.fileExists = Zotero.Promise.coroutine(function* () {
throw new Error("Zotero.Item.fileExists() cannot be called on link attachments");
}
var exists = !!(yield this.getFilePath());
yield this._updateAttachmentStates(exists);
return exists;
return !!(yield this.getFilePathAsync());
});
@ -2794,7 +2929,7 @@ Zotero.Item.prototype.__defineGetter__('attachmentModificationTime', Zotero.Prom
return undefined;
}
var path = yield this.getFilePath();
var path = yield this.getFilePathAsync();
if (!path) {
return undefined;
}
@ -2832,7 +2967,7 @@ Zotero.Item.prototype.__defineGetter__('attachmentHash', function () {
return undefined;
}
return Zotero.Utilities.Internal.md5(file);
return Zotero.Utilities.Internal.md5(file) || undefined;
});
@ -2855,6 +2990,11 @@ Zotero.Item.prototype.__defineGetter__('attachmentText', Zotero.Promise.coroutin
}
var file = this.getFile();
if (!(yield OS.File.exists(file.path))) {
file = false;
}
var cacheFile = Zotero.Fulltext.getItemCacheFile(this);
if (!file) {
if (cacheFile.exists()) {
@ -3820,7 +3960,7 @@ Zotero.Item.prototype.erase = Zotero.Promise.coroutine(function* () {
}
var parentItem = this.parentKey;
parentItem = parentItem ? yield Zotero.Items.getByLibraryAndKey(this.libraryID, parentItem) : null;
parentItem = parentItem ? Zotero.Items.getByLibraryAndKey(this.libraryID, parentItem) : null;
// // Delete associated attachment files
if (this.isAttachment()) {

View file

@ -186,7 +186,7 @@ Zotero.File = new function(){
/**
* Get the contents of a text source asynchronously
*
* @param {nsIURI|nsIFile|string spec|nsIChannel|nsIInputStream} source The source to read
* @param {nsIURI|nsIFile|string spec|string path|nsIChannel|nsIInputStream} source The source to read
* @param {String} [charset] The character set; defaults to UTF-8
* @param {Integer} [maxLength] Maximum length to fetch, in bytes
* @return {Promise} A Q promise that is resolved with the contents of the file
@ -194,6 +194,11 @@ Zotero.File = new function(){
this.getContentsAsync = function (source, charset, maxLength) {
Zotero.debug("Getting contents of " + source);
// If path is given, convert to file:// URL
if (typeof source == 'string' && !source.match(/^file:/)) {
source = 'file://' + source;
}
var options = {
charset: charset ? Zotero.CharacterSets.getName(charset) : "UTF-8",
// This doesn't seem to work -- reading an image file still throws NS_ERROR_ILLEGAL_INPUT

View file

@ -325,26 +325,29 @@ Zotero.Fulltext = new function(){
/**
* @param {String} path
* @param {Boolean} [complete=FALSE] Index the file in its entirety, ignoring maxLength
*/
var indexFile = Zotero.Promise.coroutine(function* (file, mimeType, charset, itemID, complete, isCacheFile) {
if (!file.exists()){
var indexFile = Zotero.Promise.coroutine(function* (path, contentType, charset, itemID, complete, isCacheFile) {
if (!(yield OS.File.exists(path))) {
Zotero.debug('File not found in indexFile()', 2);
return false;
}
if (!itemID){ throw ('Item ID not provided to indexFile()'); }
if (!mimeType) {
Zotero.debug("MIME type not provided in indexFile()", 1);
if (!contentType) {
Zotero.debug("Content type not provided in indexFile()", 1);
return false;
}
if (mimeType == 'application/pdf') {
return this.indexPDF(file, itemID, complete);
if (!itemID) {
throw new Error('Item ID not provided');
}
if (!Zotero.MIME.isTextType(mimeType)) {
if (contentType == 'application/pdf') {
return this.indexPDF(path, itemID, complete);
}
if (!Zotero.MIME.isTextType(contentType)) {
Zotero.debug('File is not text in indexFile()', 2);
return false;
}
@ -354,13 +357,13 @@ Zotero.Fulltext = new function(){
return false;
}
Zotero.debug('Indexing file ' + file.path);
Zotero.debug('Indexing file ' + path);
var text = yield Zotero.File.getContentsAsync(file, charset);
var text = yield Zotero.File.getContentsAsync(path, charset);
var totalChars = text.length;
var maxLength = complete ? false : Zotero.Prefs.get('fulltext.textMaxLength');
if (mimeType == 'text/html') {
if (contentType == 'text/html') {
let obj = yield convertItemHTMLToText(itemID, text, maxLength);
text = obj.text;
totalChars = obj.totalChars;
@ -394,7 +397,7 @@ Zotero.Fulltext = new function(){
* @param {Boolean} [allPages] - If true, index all pages rather than pdfMaxPages
* @return {Promise}
*/
this.indexPDF = Zotero.Promise.coroutine(function* (file, itemID, allPages) {
this.indexPDF = Zotero.Promise.coroutine(function* (filePath, itemID, allPages) {
if (!_pdfConverter) {
Zotero.debug("PDF tools are not installed -- skipping indexing");
return false;
@ -410,23 +413,22 @@ Zotero.Fulltext = new function(){
// If file is stored outside of Zotero, create a directory for the item
// in the storage directory and save the cache file there
if (linkMode == Zotero.Attachments.LINK_MODE_LINKED_FILE) {
var cacheFile = yield Zotero.Attachments.createDirectoryForItem(item);
var parentDirPath = (yield Zotero.Attachments.createDirectoryForItem(item)).path;
}
else {
var cacheFile = file.parent;
var parentDirPath = OS.Path.dirname(filePath);
}
cacheFile.append(this.pdfConverterCacheFile);
var cacheFilePath = OS.Path.join(parentDirPath, this.pdfConverterCacheFile);
if (_pdfInfo) {
var infoFile = cacheFile.parent;
infoFile.append(this.pdfInfoCacheFile);
Zotero.debug('Running pdfinfo "' + file.path + '" "' + infoFile.path + '"');
var infoFilePath = OS.Path.join(parentDirPath, this.pdfInfoCacheFile);
Zotero.debug('Running pdfinfo "' + filePath + '" "' + infoFilePath + '"');
var proc = Components.classes["@mozilla.org/process/util;1"].
createInstance(Components.interfaces.nsIProcess);
proc.init(_pdfInfo);
var args = [file.path, infoFile.path];
var args = [filePath, infoFilePath];
try {
proc.runw(true, args, args.length);
var totalPages = yield getTotalPagesFromFile(itemID);
@ -440,8 +442,8 @@ Zotero.Fulltext = new function(){
}
Zotero.debug('Running pdftotext -enc UTF-8 -nopgbrk '
+ (allPages ? '' : '-l ' + maxPages) + ' "' + file.path + '" "'
+ cacheFile.path + '"');
+ (allPages ? '' : '-l ' + maxPages) + ' "' + filePath + '" "'
+ cacheFilePath + '"');
var proc = Components.classes["@mozilla.org/process/util;1"].
createInstance(Components.interfaces.nsIProcess);
@ -457,7 +459,7 @@ Zotero.Fulltext = new function(){
args.push('-l', maxPages);
var pagesIndexed = Math.min(maxPages, totalPages);
}
args.push(file.path, cacheFile.path);
args.push(filePath, cacheFilePath);
try {
proc.runw(true, args, args.length);
}
@ -466,10 +468,11 @@ Zotero.Fulltext = new function(){
return false;
}
if (!cacheFile.exists()) {
var msg = file.leafName + " was not indexed";
if (!file.leafName.match(/^[\u0000-\u007F]+$/)) {
msg += " -- PDFs with filenames containing extended characters cannot currently be indexed due to a Firefox limitation";
if (!(yield OS.File.exists(cacheFilePath))) {
let fileName = OS.Path.basename(filePath);
let msg = fileName + " was not indexed";
if (!fileName.match(/^[\u0000-\u007F]+$/)) {
msg += " -- PDFs with filenames containing extended characters cannot currently be indexed due to a Mozilla limitation";
}
Zotero.debug(msg, 2);
Components.utils.reportError(msg);
@ -477,7 +480,7 @@ Zotero.Fulltext = new function(){
}
yield Zotero.DB.executeTransaction(function* () {
yield indexFile(cacheFile, 'text/plain', 'utf-8', itemID, true, true);
yield indexFile(cacheFilePath, 'text/plain', 'utf-8', itemID, true, true);
yield setPages(itemID, { indexed: pagesIndexed, total: totalPages });
});
@ -500,24 +503,24 @@ Zotero.Fulltext = new function(){
let itemID = item.id;
var file = yield item.getFile();
if (!file){
var path = yield item.getFilePathAsync();
if (!path) {
Zotero.debug("No file to index for item " + itemID + " in Fulltext.indexItems()");
continue;
}
if (ignoreErrors) {
try {
yield indexFile(file, item.attachmentMIMEType, item.attachmentCharset, itemID, complete);
yield indexFile(path, item.attachmentContentType, item.attachmentCharset, itemID, complete);
}
catch (e) {
Zotero.debug(e, 1);
Components.utils.reportError("Error indexing " + file.path);
Components.utils.reportError("Error indexing " + path);
Components.utils.reportError(e);
}
}
else {
yield indexFile(file, item.attachmentMIMEType, item.attachmentCharset, itemID, complete);
yield indexFile(path, item.attachmentContentType, item.attachmentCharset, itemID, complete);
}
}
});
@ -693,7 +696,7 @@ Zotero.Fulltext = new function(){
*/
this.setItemContent = Zotero.Promise.coroutine(function* (libraryID, key, text, stats, version) {
var libraryKey = libraryID + "/" + key;
var item = yield Zotero.Items.getByLibraryAndKey(libraryID, key);
var item = Zotero.Items.getByLibraryAndKey(libraryID, key);
if (!item) {
let msg = "Item " + libraryKey + " not found setting full-text content";
Zotero.debug(msg, 1);

View file

@ -1363,7 +1363,7 @@ Zotero.ItemTreeView.prototype.sort = Zotero.Promise.coroutine(function* (itemID)
case 'hasAttachment':
if (item.isAttachment()) {
var state = item.fileExists() ? 1 : -1;
var state = item.fileExistsCached() ? 1 : -1;
}
else if (item.isRegularItem()) {
var state = item.getBestAttachmentState();

View file

@ -1184,7 +1184,7 @@ Zotero.Search.prototype._buildQuery = Zotero.Promise.coroutine(function* () {
if (condition.value) {
var lkh = Zotero.Collections.parseLibraryKeyHash(condition.value);
if (lkh) {
col = yield Zotero.Collections.getByLibraryAndKey(lkh.libraryID, lkh.key);
col = Zotero.Collections.getByLibraryAndKey(lkh.libraryID, lkh.key);
}
}
if (!col) {
@ -1225,7 +1225,7 @@ Zotero.Search.prototype._buildQuery = Zotero.Promise.coroutine(function* () {
if (condition.value) {
var lkh = Zotero.Searches.parseLibraryKeyHash(condition.value);
if (lkh) {
search = yield Zotero.Searches.getByLibraryAndKey(lkh.libraryID, lkh.key);
search = Zotero.Searches.getByLibraryAndKey(lkh.libraryID, lkh.key);
}
}
if (!search) {

View file

@ -75,6 +75,10 @@ Zotero.Utilities.Internal = {
ch.update(data, data.length);
}
else if (strOrFile instanceof Components.interfaces.nsIFile) {
if (!strOrFile.exists()) {
return false;
}
// Otherwise throws (NS_ERROR_NOT_AVAILABLE) [nsICryptoHash.updateFromStream]
if (!strOrFile.fileSize) {
// MD5 for empty string

View file

@ -1512,7 +1512,7 @@ var ZoteroPane = new function()
for (var i=0; i<items.length; i++) {
// If any PDFs, we need to make sure the converter is installed and
// prompt for installation if not
if (!checkPDF && items[i].attachmentMIMEType && items[i].attachmentMIMEType == "application/pdf") {
if (!checkPDF && items[i].attachmentContentType && items[i].attachmentContentType == "application/pdf") {
checkPDF = true;
}
itemIDs.push(items[i].id);
@ -3572,7 +3572,7 @@ var ZoteroPane = new function()
continue;
}
var path = yield item.getFilePath();
var path = yield item.getFilePathAsync();
if (path) {
let file = Zotero.File.pathToFile(path);