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; var parentKey = this.item.parentKey;
if (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; 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()); var attachments = item.isAttachment() ? [item] : (yield item.getBestAttachments());
for each(var attachment in attachments) { for each(var attachment in attachments) {
if(attachment.attachmentLinkMode !== Zotero.Attachments.LINK_MODE_LINKED_URL) { if(attachment.attachmentLinkMode !== Zotero.Attachments.LINK_MODE_LINKED_URL) {
var path = yield attachment.getFilePath(); var path = yield attachment.getFilePathAsync();
if (path) { if (path) {
var ext = Zotero.File.getExtension(Zotero.File.pathToFile(path)); var ext = Zotero.File.getExtension(Zotero.File.pathToFile(path));
if(!attachment.attachmentMIMEType || 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.) // We'll index it later if it fails. (This may not be necessary.)
setTimeout(function () { setTimeout(function () {
if (contentType == 'application/pdf') { if (contentType == 'application/pdf') {
Zotero.Fulltext.indexPDF(file, attachmentItem.id); Zotero.Fulltext.indexPDF(file.path, attachmentItem.id);
} }
else if (Zotero.MIME.isTextType(contentType)) { else if (Zotero.MIME.isTextType(contentType)) {
Zotero.Fulltext.indexDocument(document, attachmentItem.id); 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 * If a directory exists with the same name, move it to orphaned-files
* *
* @param {Number} itemID - Item id * @param {Number} itemID - Item id
* @return {Promise} * @return {Promise<nsIFile>}
*/ */
this.createDirectoryForItem = Zotero.Promise.coroutine(function* (item) { this.createDirectoryForItem = Zotero.Promise.coroutine(function* (item) {
if (!(item instanceof Zotero.Item)) { if (!(item instanceof Zotero.Item)) {

View File

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

View File

@ -105,7 +105,7 @@ Zotero.DataObjects = function (object, objectPlural, id, table) {
let id = ids[i]; let id = ids[i];
// Check if already loaded // Check if already loaded
if (!this._objectCache[id]) { 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]); toReturn.push(this._objectCache[id]);
} }
@ -215,21 +215,28 @@ Zotero.DataObjects = function (object, objectPlural, id, table) {
* @param {String} key * @param {String} key
* @return {Zotero.DataObject} Zotero data object, or FALSE if not found * @return {Zotero.DataObject} Zotero data object, or FALSE if not found
*/ */
this.getByLibraryAndKey = Zotero.Promise.coroutine(function* (libraryID, key, options) { this.getByLibraryAndKey = function (libraryID, key, options) {
var sql = "SELECT ROWID FROM " + this._ZDO_table + " WHERE "; var id = this.getIDFromLibraryAndKey(libraryID, key);
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);
if (!id) { if (!id) {
return false; return false;
} }
return Zotero[this._ZDO_Objects].get(id, options); 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 // Parent item
let parentItem = this.parentKey; 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 (this._changed.parentKey) {
if (isNew) { if (isNew) {
if (!parentItem) { if (!parentItem) {
@ -1394,7 +1394,7 @@ Zotero.Item.prototype.save = Zotero.Promise.coroutine(function* (options) {
var oldParentKey = this._previousData.parentKey; var oldParentKey = this._previousData.parentKey;
if (oldParentKey) { if (oldParentKey) {
var oldParentItem = yield Zotero.Items.getByLibraryAndKey(this.libraryID, oldParentKey); var oldParentItem = Zotero.Items.getByLibraryAndKey(this.libraryID, oldParentKey);
if (oldParentItem) { if (oldParentItem) {
let oldParentItemNotifierData = {}; let oldParentItemNotifierData = {};
//oldParentItemNotifierData[oldParentItem.id] = {}; //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 * @return {nsILocalFile|false} An nsIFile, or false for invalid paths
*/ */
Zotero.Item.prototype.getFile = function (skipExistsCheck) { Zotero.Item.prototype.getFile = function () {
if (arguments.length > 1) { if (arguments.length) {
Zotero.debug("WARNING: Zotero.Item.prototype.getFile() no longer takes two parameters"); Zotero.debug("WARNING: Zotero.Item.prototype.getFile() no longer takes any arguments");
} }
if (!this.isAttachment()) { if (!this.isAttachment()) {
@ -2186,21 +2188,17 @@ Zotero.Item.prototype.getFile = function (skipExistsCheck) {
} }
} }
if (!skipExistsCheck && !file.exists()) {
return false;
}
return file; 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 * @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()) { if (!this.isAttachment()) {
throw new Error("getFilePath() can only be called on attachment items"); 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) { if (!path) {
Zotero.debug("Attachment path is empty", 2); Zotero.debug("Attachment path is empty", 2);
if (!skipExistsCheck) { 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; return false;
} }
@ -2269,7 +2397,7 @@ Zotero.Item.prototype.getFilePath = Zotero.Promise.coroutine(function* (skipExis
catch (e) { catch (e) {
Zotero.debug('Invalid persistent descriptor', 2); Zotero.debug('Invalid persistent descriptor', 2);
if (!skipExistsCheck) { if (!skipExistsCheck) {
yield this._updateAttachmentStates(false); this._updateAttachmentStates(false);
} }
return false; return false;
} }
@ -2280,7 +2408,7 @@ Zotero.Item.prototype.getFilePath = Zotero.Promise.coroutine(function* (skipExis
path.indexOf(Zotero.Attachments.BASE_PATH_PLACEHOLDER) == 0) { path.indexOf(Zotero.Attachments.BASE_PATH_PLACEHOLDER) == 0) {
var file = Zotero.Attachments.resolveRelativePath(path); var file = Zotero.Attachments.resolveRelativePath(path);
if (!skipExistsCheck && !file) { if (!skipExistsCheck && !file) {
yield this._updateAttachmentStates(false); this._updateAttachmentStates(false);
return false; return false;
} }
} }
@ -2307,32 +2435,33 @@ Zotero.Item.prototype.getFilePath = Zotero.Promise.coroutine(function* (skipExis
catch (e) { catch (e) {
Zotero.debug('Invalid relative descriptor', 2); Zotero.debug('Invalid relative descriptor', 2);
if (!skipExistsCheck) { if (!skipExistsCheck) {
yield this._updateAttachmentStates(false); this._updateAttachmentStates(false);
} }
return false; return false;
} }
} }
} }
path = file.path; var path = file.path;
if (!skipExistsCheck && !(yield OS.File.exists(path))) { if (!skipExistsCheck && !(yield OS.File.exists(path))) {
Zotero.debug("Attachment file '" + path + "' not found", 2); Zotero.debug("Attachment file '" + path + "' not found", 2);
yield this._updateAttachmentStates(false); this._updateAttachmentStates(false);
return false; return false;
} }
if (!skipExistsCheck) { 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 * 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; this._fileExists = exists;
if (this.isTopLevelItem()) { if (this.isTopLevelItem()) {
@ -2351,9 +2480,18 @@ Zotero.Item.prototype._updateAttachmentStates = Zotero.Promise.coroutine(functio
return; 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(); item.clearBestAttachmentState();
}); };
Zotero.Item.prototype.getFilename = function () { Zotero.Item.prototype.getFilename = function () {
@ -2366,7 +2504,6 @@ Zotero.Item.prototype.getFilename = function () {
} }
var file = this.getFile(); var file = this.getFile();
// Invalid path
if (!file) { if (!file) {
return ''; return '';
} }
@ -2377,7 +2514,7 @@ Zotero.Item.prototype.getFilename = function () {
/** /**
* Asynchronous cached check for file existence, used for items view * 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* () { Zotero.Item.prototype.fileExists = Zotero.Promise.coroutine(function* () {
if (this._fileExists !== null) { 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"); throw new Error("Zotero.Item.fileExists() cannot be called on link attachments");
} }
var exists = !!(yield this.getFilePath()); return !!(yield this.getFilePathAsync());
yield this._updateAttachmentStates(exists);
return exists;
}); });
@ -2794,7 +2929,7 @@ Zotero.Item.prototype.__defineGetter__('attachmentModificationTime', Zotero.Prom
return undefined; return undefined;
} }
var path = yield this.getFilePath(); var path = yield this.getFilePathAsync();
if (!path) { if (!path) {
return undefined; return undefined;
} }
@ -2832,7 +2967,7 @@ Zotero.Item.prototype.__defineGetter__('attachmentHash', function () {
return undefined; 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(); var file = this.getFile();
if (!(yield OS.File.exists(file.path))) {
file = false;
}
var cacheFile = Zotero.Fulltext.getItemCacheFile(this); var cacheFile = Zotero.Fulltext.getItemCacheFile(this);
if (!file) { if (!file) {
if (cacheFile.exists()) { if (cacheFile.exists()) {
@ -3820,7 +3960,7 @@ Zotero.Item.prototype.erase = Zotero.Promise.coroutine(function* () {
} }
var parentItem = this.parentKey; 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 // // Delete associated attachment files
if (this.isAttachment()) { if (this.isAttachment()) {

View File

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

View File

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

View File

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

View File

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

View File

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