commit 40ec3442182571f7e6e6847758fabe27907e9eab
parent 7b902f0fd4d97e19d6c54d8e6308e219bc284fbb
Author: Dan Stillman <dstillman@zotero.org>
Date: Sat, 15 Oct 2011 05:50:30 +0000
Fix a number of problems related to newlines in filenames
- Properly strip newlines and tabs in filenames (broken since May 2011)
- If view isn't editable, don't show Locate button, since the updated path couldn't be sent back up
- Fix access error if a synced file needs to be renamed to be valid but user doesn't have group editing access
- Don't allow newlines in item titles (e.g., via copy/paste)
Diffstat:
5 files changed, 57 insertions(+), 10 deletions(-)
diff --git 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
@@ -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
@@ -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
@@ -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
@@ -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