diff --git a/chrome/content/zotero/xpcom/data/item.js b/chrome/content/zotero/xpcom/data/item.js index f55c7df34e..5dc2efb48c 100644 --- a/chrome/content/zotero/xpcom/data/item.js +++ b/chrome/content/zotero/xpcom/data/item.js @@ -73,6 +73,7 @@ Zotero.Item.prototype._init = function () { this._changedSource = false; this._changedAttachmentData = false; + this._skipModTimeUpdate = false; this._previousData = null; this._deleted = null; @@ -647,7 +648,7 @@ Zotero.Item.prototype.inCollection = function(collectionID) { */ Zotero.Item.prototype.setField = function(field, value, loadIn) { if (typeof value == 'string') { - value = Zotero.Utilities.trim(value); + value = value.trim(); } this._disabledCheck(); @@ -768,6 +769,11 @@ Zotero.Item.prototype.setField = function(field, value, loadIn) { } } + // If not a multiline field, strip newlines + if (typeof value == 'string' && !Zotero.ItemFields.isMultiline(fieldID)) { + value = value.replace(/[\r\n]+/g, " ");; + } + if (!loadIn) { // Save date field as multipart date // TEMP - filingDate @@ -1586,7 +1592,8 @@ Zotero.Item.prototype.save = function() { sql += field + '=?, '; sqlValues.push(this.getField(field)); } - else if (field == 'dateModified' || field == 'clientDateModified') { + else if ((field == 'dateModified' || field == 'clientDateModified') + && !this._skipModTimeUpdate) { sql += field + '=?, '; sqlValues.push(Zotero.DB.transactionDateTime); } @@ -1595,7 +1602,9 @@ Zotero.Item.prototype.save = function() { sql = sql.substr(0, sql.length-2) + " WHERE itemID=?"; sqlValues.push({ int: this.id }); - Zotero.DB.query(sql, sqlValues); + if (sqlValues.length > 1) { + Zotero.DB.query(sql, sqlValues); + } // @@ -2755,7 +2764,14 @@ Zotero.Item.prototype.renameAttachmentFile = function(newName, overwrite) { } -Zotero.Item.prototype.relinkAttachmentFile = function(file) { +/** + * @param {Boolean} [skipItemUpdate] Don't update attachment item mod time, + * so that item doesn't sync. Used when a file + * needs to be renamed to be accessible but the + * user doesn't have access to modify the + * attachment metadata + */ +Zotero.Item.prototype.relinkAttachmentFile = function(file, skipItemUpdate) { var linkMode = this.attachmentLinkMode; if (linkMode == Zotero.Attachments.LINK_MODE_LINKED_URL) { throw('Cannot relink linked URL in Zotero.Items.relinkAttachmentFile()'); @@ -2774,6 +2790,10 @@ Zotero.Item.prototype.relinkAttachmentFile = function(file) { var path = Zotero.Attachments.getPath(file, linkMode); this.attachmentPath = path; + + if (skipItemUpdate) { + this._skipModTimeUpdate = true; + } this.save(); return false; diff --git a/chrome/content/zotero/xpcom/data/itemFields.js b/chrome/content/zotero/xpcom/data/itemFields.js index 1494125382..6af62f619c 100644 --- a/chrome/content/zotero/xpcom/data/itemFields.js +++ b/chrome/content/zotero/xpcom/data/itemFields.js @@ -148,6 +148,14 @@ Zotero.ItemFields = new function() { } + this.isMultiline = function (fieldID) { + _fieldCheck(fieldID, 'isMultiline'); + + // TEMP: extra and abstractNote + return 22 || 90; + } + + this.isCustom = function (fieldID) { _fieldCheck(fieldID, 'isCustom'); diff --git a/chrome/content/zotero/xpcom/file.js b/chrome/content/zotero/xpcom/file.js index 873504b1dd..2aa49c1d92 100644 --- a/chrome/content/zotero/xpcom/file.js +++ b/chrome/content/zotero/xpcom/file.js @@ -226,7 +226,7 @@ Zotero.File = new function(){ // URL encode when saving attachments that trigger this fileName = fileName.replace(/[\/\\\?%\*:|"<>]/g, ''); // Replace newlines and tabs (which shouldn't be in the string in the first place) with spaces - fileName = fileName.replace(/\n\t/g, ' '); + fileName = fileName.replace(/[\n\t]/g, ' '); if (!skipXML) { // Strip characters not valid in XML, since they won't sync and they're probably unwanted fileName = fileName.replace(/[\u0000-\u0008\u000b\u000c\u000e-\u001f\ud800-\udfff\ufffe\uffff]/g, ''); diff --git a/chrome/content/zotero/xpcom/storage.js b/chrome/content/zotero/xpcom/storage.js index bdbfe74daf..b1142072b1 100644 --- a/chrome/content/zotero/xpcom/storage.js +++ b/chrome/content/zotero/xpcom/storage.js @@ -653,16 +653,29 @@ Zotero.Sync.Storage = new function () { var newFile = _processDownload(item); } - // If |updated| is a file, it was renamed, so set item filename to that + // If |newFile| is set, the file was renamed, so set item filename to that // and mark for updated var file = item.getFile(); if (newFile && file.leafName != newFile.leafName) { _updatesInProgress = true; - item.relinkAttachmentFile(newFile); - _updatesInProgress = false; + + // If library isn't editable but filename was changed, update + // database without updating the item's mod time, which would result + // in a library access error + if (!Zotero.Items.editCheck(item)) { + Zotero.debug("File renamed without library access -- updating itemAttachments path", 3); + item.relinkAttachmentFile(newFile, true); + var useCurrentModTime = false; + } + else { + item.relinkAttachmentFile(newFile); + + // TODO: use an integer counter instead of mod time for change detection + var useCurrentModTime = true; + } + file = item.getFile(); - // TODO: use an integer counter instead of mod time for change detection - var useCurrentModTime = true; + _updatesInProgress = false; } else { var useCurrentModTime = false; diff --git a/chrome/content/zotero/zoteroPane.js b/chrome/content/zotero/zoteroPane.js index 551b127297..07571dd80b 100644 --- a/chrome/content/zotero/zoteroPane.js +++ b/chrome/content/zotero/zoteroPane.js @@ -3336,6 +3336,12 @@ var ZoteroPane = new function() function viewAttachment(itemIDs, event, noLocateOnMissing, forceExternalViewer) { + // If view isn't editable, don't show Locate button, since the updated + // path couldn't be sent back up + if (!this.itemsView.editable) { + noLocateOnMissing = true; + } + if(typeof itemIDs != "object") itemIDs = [itemIDs]; // If multiple items, set up event so we open in new tab