www

Unnamed repository; edit this file 'description' to name the repository.
Log | Files | Refs | Submodules | README | LICENSE

commit b75cc8f9d0cccc03bec937121e230ddeb3785fa4
parent bd1092e519c18ad437c6330ebb749562d77bcd56
Author: Adomas VenĨkauskas <adomas.ven@gmail.com>
Date:   Wed,  4 Nov 2015 19:30:25 +0000

Closes #437, Detect when data directory is in Dropbox

Display a warning when choosing data directory
Or on opening Zotero Pane for existing users with data dir in dropbox

Also:
Fix a bug where it won't use custom path if "Choose..." button is
pressed instead of radio button.
Change filepicker to show current data directory on display

Diffstat:
Mchrome/content/zotero/overlay.js | 4++++
Mchrome/content/zotero/preferences/preferences_advanced.js | 61+++++++++++++++++--------------------------------------------
Mchrome/content/zotero/preferences/preferences_advanced.xul | 5+----
Mchrome/content/zotero/xpcom/file.js | 5+++++
Mchrome/content/zotero/xpcom/zotero.js | 96+++++++++++++++++++++++++++++++++++++++++++++++++------------------------------
Mchrome/locale/en-US/zotero/zotero.properties | 4++++
Mdefaults/preferences/zotero.js | 1+
7 files changed, 92 insertions(+), 84 deletions(-)

diff --git a/chrome/content/zotero/overlay.js b/chrome/content/zotero/overlay.js @@ -210,6 +210,10 @@ var ZoteroOverlay = new function() // Make visible ZoteroPane.makeVisible(); + // Warn about unsafe data directory on first display + let dataDir = Zotero.getZoteroDirectory(); + Zotero.checkForUnsafeDataDirectory(dataDir.path); + // Make sure tags splitter isn't missing for people upgrading from <2.0b7 document.getElementById('zotero-tags-splitter').collapsed = false; } else { diff --git a/chrome/content/zotero/preferences/preferences_advanced.js b/chrome/content/zotero/preferences/preferences_advanced.js @@ -198,59 +198,32 @@ Zotero_Preferences.Advanced = { onDataDirUpdate: function (event) { var radiogroup = document.getElementById('dataDir'); - var path = document.getElementById('dataDirPath'); var useDataDir = Zotero.Prefs.get('useDataDir'); + var newUseDataDir = radiogroup.selectedIndex == 1; - // If triggered from the Choose button, don't show the dialog, since - // Zotero.chooseZoteroDirectory() (called below due to the radio button - // change) shows its own - if (event.originalTarget && event.originalTarget.tagName == 'button') { - return true; + if (newUseDataDir == useDataDir && !useDataDir) { + return; } - - // If changing from default to custom - if (!useDataDir) { - event.stopPropagation(); - var file = Zotero.chooseZoteroDirectory(true, false, function () { - Zotero_Preferences.openURL('http://zotero.org/support/zotero_data'); - }); - radiogroup.selectedIndex = file ? 1 : 0; - return !!file; - } - - var ps = Components.classes["@mozilla.org/embedcomp/prompt-service;1"] - .getService(Components.interfaces.nsIPromptService); - var buttonFlags = ps.BUTTON_POS_0 * ps.BUTTON_TITLE_IS_STRING - + ps.BUTTON_POS_1 * ps.BUTTON_TITLE_CANCEL - + ps.BUTTON_POS_2 * ps.BUTTON_TITLE_IS_STRING; - var app = Zotero.appName; - var index = ps.confirmEx(window, - Zotero.getString('general.restartRequired'), - Zotero.getString('general.restartRequiredForChange', app) + '\n\n' - + Zotero.getString('dataDir.moveFilesToNewLocation', app), - buttonFlags, - Zotero.getString('general.quitApp', app), - null, - Zotero.getString('general.moreInformation'), - null, {}); - - if (index == 0) { - useDataDir = !!radiogroup.selectedIndex; - // quit() is asynchronous, but set this here just in case - Zotero.Prefs.set('useDataDir', useDataDir); - var appStartup = Components.classes["@mozilla.org/toolkit/app-startup;1"] - .getService(Components.interfaces.nsIAppStartup); - appStartup.quit(Components.interfaces.nsIAppStartup.eAttemptQuit); - } - else if (index == 2) { + + // This call shows a filepicker if needed, + // forces a restart if required + // and does nothing if cancel was pressed + Zotero.chooseZoteroDirectory(true, !newUseDataDir, function () { Zotero_Preferences.openURL('http://zotero.org/support/zotero_data'); - } - + }); + useDataDir = Zotero.Prefs.get('useDataDir'); radiogroup.selectedIndex = useDataDir ? 1 : 0; + return useDataDir; }, + chooseDataDir: function(event) { + document.getElementById('dataDir').selectedIndex = 1; + //this.onDataDirUpdate(event); + }, + + getDataDirPath: function () { var desc = Zotero.Prefs.get('dataDir'); if (desc == '') { diff --git a/chrome/content/zotero/preferences/preferences_advanced.xul b/chrome/content/zotero/preferences/preferences_advanced.xul @@ -181,10 +181,7 @@ onsyncfrompreference="return Zotero_Preferences.Advanced.getDataDirPath();" readonly="true" flex="1"/> <button label="&zotero.preferences.dataDir.choose;" - oncommand="var file = Zotero.chooseZoteroDirectory(true); - if (!file) { - event.stopPropagation(); - }"/> + oncommand="return Zotero_Preferences.Advanced.chooseDataDir(event)"/> </hbox> </radiogroup> diff --git a/chrome/content/zotero/xpcom/file.js b/chrome/content/zotero/xpcom/file.js @@ -1024,4 +1024,9 @@ Zotero.File = new function(){ throw e; } + + + this.isDropboxDirectory = function(path) { + return path.toLowerCase().indexOf('dropbox') != -1; + } } diff --git a/chrome/content/zotero/xpcom/zotero.js b/chrome/content/zotero/xpcom/zotero.js @@ -381,7 +381,9 @@ Components.utils.import("resource://gre/modules/osfile.jsm"); return false; } } - + if(Zotero.isStandalone) { + Zotero.checkForUnsafeDataDirectory(dataDir.path); + } // Register shutdown handler to call Zotero.shutdown() var _shutdownObserver = {observe:function() { Zotero.shutdown().done() }}; Services.obs.addObserver(_shutdownObserver, "quit-application", false); @@ -1066,56 +1068,50 @@ Components.utils.import("resource://gre/modules/osfile.jsm"); var fp = Components.classes["@mozilla.org/filepicker;1"] .createInstance(nsIFilePicker); fp.init(win, Zotero.getString('dataDir.selectDir'), nsIFilePicker.modeGetFolder); + fp.displayDirectory = Zotero.getZoteroDirectory(); fp.appendFilters(nsIFilePicker.filterAll); if (fp.show() == nsIFilePicker.returnOK) { var file = fp.file; - - if (file.directoryEntries.hasMoreElements()) { - var dbfile = file.clone(); + let dialogText = ''; + let dialogTitle = ''; + + // In dropbox folder + if (Zotero.File.isDropboxDirectory(file.path)) { + dialogTitle = Zotero.getString('general.warning'); + dialogText = Zotero.getString('dataDir.unsafeLocation.selected.dropbox') + "\n\n" + + Zotero.getString('dataDir.unsafeLocation.selected.useAnyway'); + } + else if (file.directoryEntries.hasMoreElements()) { + let dbfile = file.clone(); dbfile.append('zotero.sqlite'); // Warn if non-empty and no zotero.sqlite if (!dbfile.exists()) { - var buttonFlags = ps.STD_YES_NO_BUTTONS; - if (moreInfoCallback) { - buttonFlags += ps.BUTTON_POS_2 * ps.BUTTON_TITLE_IS_STRING; - } - var index = ps.confirmEx(null, - Zotero.getString('dataDir.selectedDirNonEmpty.title'), - Zotero.getString('dataDir.selectedDirNonEmpty.text'), - buttonFlags, - null, - null, - moreInfoCallback ? Zotero.getString('general.help') : null, - null, {}); - - // Not OK -- return to file picker - if (index == 1) { - continue; - } - else if (index == 2) { - setTimeout(function () { - moreInfoCallback(); - }, 1); - return false; - } + dialogTitle = Zotero.getString('dataDir.selectedDirNonEmpty.title'); + dialogText = Zotero.getString('dataDir.selectedDirNonEmpty.text'); } } + // Directory empty else { - var buttonFlags = ps.STD_YES_NO_BUTTONS; + dialogTitle = Zotero.getString('dataDir.selectedDirEmpty.title'); + dialogText = Zotero.getString('dataDir.selectedDirEmpty.text', Zotero.appName) + '\n\n' + + Zotero.getString('dataDir.selectedDirEmpty.useNewDir'); + } + // Warning dialog to be displayed + if(dialogText !== '') { + let buttonFlags = ps.STD_YES_NO_BUTTONS; if (moreInfoCallback) { buttonFlags += ps.BUTTON_POS_2 * ps.BUTTON_TITLE_IS_STRING; } - var index = ps.confirmEx(null, - Zotero.getString('dataDir.selectedDirEmpty.title'), - Zotero.getString('dataDir.selectedDirEmpty.text', Zotero.appName) + '\n\n' - + Zotero.getString('dataDir.selectedDirEmpty.useNewDir'), + let index = ps.confirmEx(null, + dialogTitle, + dialogText, buttonFlags, null, null, moreInfoCallback ? Zotero.getString('general.moreInformation') : null, null, {}); - + // Not OK -- return to file picker if (index == 1) { continue; @@ -1127,8 +1123,7 @@ Components.utils.import("resource://gre/modules/osfile.jsm"); return false; } } - - + // Set new data directory Zotero.Prefs.set('dataDir', file.persistentDescriptor); Zotero.Prefs.set('lastDataDir', file.path); @@ -1156,12 +1151,41 @@ Components.utils.import("resource://gre/modules/osfile.jsm"); forceQuitNow ? null : Zotero.getString('general.restartLater'), null, null, {}); - if (index == 0) { + if (forceQuitNow || index == 0) { Services.startup.quit(Components.interfaces.nsIAppStartup.eAttemptQuit); } return useProfileDir ? true : file; } + + + this.warnOnUnsafeDataDir = true; + this.checkForUnsafeDataDirectory = function (path) { + if (this.warnOnUnsafeDataDir && Zotero.File.isDropboxDirectory(path) + && Zotero.Prefs.get('warnOnUnsafeDataDir')) { + + this.warnOnUnsafeDataDir = false; + let check = {value: false}; + let index = Services.prompt.confirmEx( + null, + Zotero.getString('general.warning'), + Zotero.getString('dataDir.unsafeLocation.existing.dropbox') + "\n\n" + + Zotero.getString('dataDir.unsafeLocation.existing.chooseDifferent'), + Services.prompt.STD_YES_NO_BUTTONS, + null, null, null, + Zotero.getString('general.dontShowWarningAgain'), + check + ); + + // Yes - display dialog. + if (index == 0) { + Zotero.chooseZoteroDirectory(true); + } + if (check.value) { + Zotero.Prefs.set('warnOnUnsafeDataDir', false); + } + } + } /** diff --git a/chrome/locale/en-US/zotero/zotero.properties b/chrome/locale/en-US/zotero/zotero.properties @@ -112,6 +112,10 @@ dataDir.notFound = The Zotero data directory could not be found. dataDir.previousDir = Previous directory: dataDir.useProfileDir = Use %S profile directory dataDir.selectDir = Select a Zotero data directory +dataDir.unsafeLocation.selected.dropbox = Choosing a data directory within Dropbox may corrupt your database. +dataDir.unsafeLocation.selected.useAnyway = Use this directory anyway? +dataDir.unsafeLocation.existing.dropbox = Your Zotero data directory is within Dropbox, which may lead to data corruption. +dataDir.unsafeLocation.existing.chooseDifferent = Would you like to choose a different location now? dataDir.selectedDirNonEmpty.title = Directory Not Empty dataDir.selectedDirNonEmpty.text = The directory you selected is not empty and does not appear to be a Zotero data directory.\n\nCreate Zotero files in this directory anyway? dataDir.selectedDirEmpty.title = Directory Empty diff --git a/defaults/preferences/zotero.js b/defaults/preferences/zotero.js @@ -11,6 +11,7 @@ pref("extensions.zotero.baseAttachmentPath", ''); pref("extensions.zotero.useDataDir", false); pref("extensions.zotero.dataDir", ''); pref("extensions.zotero.lastDataDir", ''); +pref("extensions.zotero.warnOnUnsafeDataDir", true); pref("extensions.zotero.debug.log",false); pref("extensions.zotero.debug.stackTrace", false); pref("extensions.zotero.debug.store",false);