zotero/chrome/content/zotero/preferences/preferences_advanced.js

805 lines
24 KiB
JavaScript
Raw Normal View History

/*
***** BEGIN LICENSE BLOCK *****
Copyright © 20062013 Center for History and New Media
George Mason University, Fairfax, Virginia, USA
http://zotero.org
This file is part of Zotero.
Zotero is free software: you can redistribute it and/or modify
it under the terms of the GNU Affero General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
Zotero is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU Affero General Public License for more details.
You should have received a copy of the GNU Affero General Public License
along with Zotero. If not, see <http://www.gnu.org/licenses/>.
***** END LICENSE BLOCK *****
*/
"use strict";
Zotero_Preferences.Advanced = {
_openURLResolvers: null,
init: function () {
Zotero_Preferences.Debug_Output.init();
},
revealDataDirectory: function () {
var dataDir = Zotero.getZoteroDirectory();
dataDir.QueryInterface(Components.interfaces.nsILocalFile);
try {
dataDir.reveal();
}
catch (e) {
// On platforms that don't support nsILocalFile.reveal() (e.g. Linux),
// launch the directory
window.opener.ZoteroPane_Local.launchFile(dataDir);
}
},
runIntegrityCheck: function () {
var ps = Components.classes["@mozilla.org/embedcomp/prompt-service;1"]
.getService(Components.interfaces.nsIPromptService);
var ok = Zotero.DB.integrityCheck();
if (ok) {
ok = Zotero.Schema.integrityCheck();
if (!ok) {
var buttonFlags = (ps.BUTTON_POS_0) * (ps.BUTTON_TITLE_IS_STRING)
+ (ps.BUTTON_POS_1) * (ps.BUTTON_TITLE_CANCEL);
var index = ps.confirmEx(window,
Zotero.getString('general.failed'),
Zotero.getString('db.integrityCheck.failed') + "\n\n" +
Zotero.getString('db.integrityCheck.repairAttempt') + " " +
Zotero.getString('db.integrityCheck.appRestartNeeded', Zotero.appName),
buttonFlags,
Zotero.getString('db.integrityCheck.fixAndRestart', Zotero.appName),
null, null, null, {}
);
if (index == 0) {
// Safety first
Zotero.DB.backupDatabase();
// Fix the errors
Zotero.Schema.integrityCheck(true);
// And run the check again
ok = Zotero.Schema.integrityCheck();
var buttonFlags = (ps.BUTTON_POS_0) * (ps.BUTTON_TITLE_IS_STRING);
if (ok) {
var str = 'success';
var msg = Zotero.getString('db.integrityCheck.errorsFixed');
}
else {
var str = 'failed';
var msg = Zotero.getString('db.integrityCheck.errorsNotFixed')
+ "\n\n" + Zotero.getString('db.integrityCheck.reportInForums');
}
ps.confirmEx(window,
Zotero.getString('general.' + str),
msg,
buttonFlags,
Zotero.getString('general.restartApp', Zotero.appName),
null, null, null, {}
);
var appStartup = Components.classes["@mozilla.org/toolkit/app-startup;1"]
.getService(Components.interfaces.nsIAppStartup);
appStartup.quit(Components.interfaces.nsIAppStartup.eAttemptQuit
| Components.interfaces.nsIAppStartup.eRestart);
}
return;
}
}
var str = ok ? 'passed' : 'failed';
ps.alert(window,
Zotero.getString('general.' + str),
Zotero.getString('db.integrityCheck.' + str)
+ (!ok ? "\n\n" + Zotero.getString('db.integrityCheck.dbRepairTool') : ''));
},
resetTranslatorsAndStyles: function () {
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);
var index = ps.confirmEx(null,
Zotero.getString('general.warning'),
Zotero.getString('zotero.preferences.advanced.resetTranslatorsAndStyles.changesLost'),
buttonFlags,
Zotero.getString('zotero.preferences.advanced.resetTranslatorsAndStyles'),
null, null, null, {});
if (index == 0) {
Zotero.Schema.resetTranslatorsAndStyles(function (xmlhttp, updated) {
this.populateQuickCopyList();
});
}
},
resetTranslators: function () {
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);
var index = ps.confirmEx(null,
Zotero.getString('general.warning'),
Zotero.getString('zotero.preferences.advanced.resetTranslators.changesLost'),
buttonFlags,
Zotero.getString('zotero.preferences.advanced.resetTranslators'),
null, null, null, {});
if (index == 0) {
Zotero.Schema.resetTranslators();
}
},
resetStyles: function () {
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);
var index = ps.confirmEx(null,
Zotero.getString('general.warning'),
Zotero.getString('zotero.preferences.advanced.resetStyles.changesLost'),
buttonFlags,
Zotero.getString('zotero.preferences.advanced.resetStyles'),
null, null, null, {});
if (index == 0) {
var self = this;
Zotero.Schema.resetStyles(function (xmlhttp, updated) {
self.populateQuickCopyList();
});
}
},
onDataDirLoad: function () {
var path = document.getElementById('dataDirPath');
var useDataDir = Zotero.Prefs.get('useDataDir');
path.setAttribute('disabled', !useDataDir);
},
onDataDirUpdate: function (event) {
var radiogroup = document.getElementById('dataDir');
var path = document.getElementById('dataDirPath');
var useDataDir = Zotero.Prefs.get('useDataDir');
// 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 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) {
Zotero_Preferences.openURL('http://zotero.org/support/zotero_data');
}
radiogroup.selectedIndex = useDataDir ? 1 : 0;
return useDataDir;
},
getDataDirPath: function () {
var desc = Zotero.Prefs.get('dataDir');
if (desc == '') {
return '';
}
var file = Components.classes["@mozilla.org/file/local;1"].
createInstance(Components.interfaces.nsILocalFile);
try {
file.persistentDescriptor = desc;
}
catch (e) {
return '';
}
return file.path;
},
populateOpenURLResolvers: function () {
var openURLMenu = document.getElementById('openURLMenu');
this._openURLResolvers = Zotero.OpenURL.discoverResolvers();
var i = 0;
for each(var r in this._openURLResolvers) {
openURLMenu.insertItemAt(i, r.name);
if (r.url == Zotero.Prefs.get('openURL.resolver') && r.version == Zotero.Prefs.get('openURL.version')) {
openURLMenu.selectedIndex = i;
}
i++;
}
var button = document.getElementById('openURLSearchButton');
switch (this._openURLResolvers.length) {
case 0:
var num = 'zero';
break;
case 1:
var num = 'singular';
break;
default:
var num = 'plural';
}
button.setAttribute('label', Zotero.getString('zotero.preferences.openurl.resolversFound.' + num, this._openURLResolvers.length));
},
onOpenURLSelected: function () {
var openURLServerField = document.getElementById('openURLServerField');
var openURLVersionMenu = document.getElementById('openURLVersionMenu');
var openURLMenu = document.getElementById('openURLMenu');
if(openURLMenu.value == "custom")
{
openURLServerField.focus();
}
else
{
openURLServerField.value = this._openURLResolvers[openURLMenu.selectedIndex]['url'];
openURLVersionMenu.value = this._openURLResolvers[openURLMenu.selectedIndex]['version'];
Zotero.Prefs.set("openURL.resolver", this._openURLResolvers[openURLMenu.selectedIndex]['url']);
Zotero.Prefs.set("openURL.version", this._openURLResolvers[openURLMenu.selectedIndex]['version']);
}
},
onOpenURLCustomized: function () {
document.getElementById('openURLMenu').value = "custom";
}
};
Zotero_Preferences.Attachment_Base_Directory = {
choosePath: function () {
// Get existing base directory
var oldBasePath = Zotero.Prefs.get('baseAttachmentPath');
if (oldBasePath) {
var oldBasePathFile = Components.classes["@mozilla.org/file/local;1"]
.createInstance(Components.interfaces.nsILocalFile);
try {
oldBasePathFile.persistentDescriptor = oldBasePath;
}
catch (e) {
Zotero.debug(e, 1);
Components.utils.reportError(e);
oldBasePathFile = null;
}
}
//Prompt user to choose new base path
var nsIFilePicker = Components.interfaces.nsIFilePicker;
var fp = Components.classes["@mozilla.org/filepicker;1"]
.createInstance(nsIFilePicker);
if (oldBasePathFile) {
fp.displayDirectory = oldBasePathFile;
}
fp.init(window, Zotero.getString('attachmentBasePath.selectDir'), nsIFilePicker.modeGetFolder);
fp.appendFilters(nsIFilePicker.filterAll);
if (fp.show() != nsIFilePicker.returnOK) {
return false;
}
var newBasePathFile = fp.file;
if (oldBasePathFile && oldBasePathFile.equals(newBasePathFile)) {
Zotero.debug("Base directory hasn't changed");
return false;
}
// Find all current attachments with relative attachment paths
var sql = "SELECT itemID FROM itemAttachments WHERE linkMode=? AND path LIKE '"
+ Zotero.Attachments.BASE_PATH_PLACEHOLDER + "%'";
var params = [Zotero.Attachments.LINK_MODE_LINKED_FILE];
var oldRelativeAttachmentIDs = Zotero.DB.columnQuery(sql, params) || [];
//Find all attachments on the new base path
var sql = "SELECT itemID FROM itemAttachments WHERE linkMode=?";
var params = [Zotero.Attachments.LINK_MODE_LINKED_FILE];
var allAttachments = Zotero.DB.columnQuery(sql,params);
var newAttachmentPaths = {};
var numNewAttachments = 0;
var numOldAttachments = 0;
var attachmentFile = Components.classes["@mozilla.org/file/local;1"]
.createInstance(Components.interfaces.nsILocalFile);
for (let i=0; i<allAttachments.length; i++) {
let attachmentID = allAttachments[i];
let relPath = false
try {
let attachment = Zotero.Items.get(attachmentID);
// This will return FALSE for relative paths if base directory
// isn't currently set
attachmentFile = attachment.getFile(false, true);
// Get existing relative path
let path = attachment.attachmentPath;
if (path.indexOf(Zotero.Attachments.BASE_PATH_PLACEHOLDER) == 0) {
relPath = path.substr(Zotero.Attachments.BASE_PATH_PLACEHOLDER.length);
}
}
catch (e) {
// Don't deal with bad attachment paths. Just skip them.
Zotero.debug(e, 2);
continue;
}
// If a file with the same relative path exists within the new base directory,
// don't touch the attachment, since it will continue to work
if (relPath) {
let relFile = Components.classes["@mozilla.org/file/local;1"]
.createInstance(Components.interfaces.nsILocalFile);
relFile.setRelativeDescriptor(newBasePathFile, relPath);
if (relFile.exists()) {
numNewAttachments++;
continue;
}
}
// Files within the new base directory need to be updated to use
// relative paths (or, if the new base directory is an ancestor or
// descendant of the old one, new relative paths)
if (attachmentFile && Zotero.File.directoryContains(newBasePathFile, attachmentFile)) {
newAttachmentPaths[attachmentID] = relPath
? attachmentFile.persistentDescriptor : null;
numNewAttachments++;
}
// Existing relative attachments not within the new base directory
// will be converted to absolute paths
else if (relPath && oldBasePathFile) {
newAttachmentPaths[attachmentID] = attachmentFile.persistentDescriptor;
numOldAttachments++;
}
}
//Confirm change of the base path
var ps = Components.classes["@mozilla.org/embedcomp/prompt-service;1"]
.getService(Components.interfaces.nsIPromptService);
var chooseStrPrefix = 'attachmentBasePath.chooseNewPath.';
var clearStrPrefix = 'attachmentBasePath.clearBasePath.';
var title = Zotero.getString(chooseStrPrefix + 'title');
var msg1 = Zotero.getString(chooseStrPrefix + 'message') + "\n\n", msg2 = "", msg3 = "";
switch (numNewAttachments) {
case 0:
break;
case 1:
msg2 += Zotero.getString(chooseStrPrefix + 'existingAttachments.singular') + " ";
break;
default:
msg2 += Zotero.getString(chooseStrPrefix + 'existingAttachments.plural', numNewAttachments) + " ";
}
switch (numOldAttachments) {
case 0:
break;
case 1:
msg3 += Zotero.getString(clearStrPrefix + 'existingAttachments.singular');
break;
default:
msg3 += Zotero.getString(clearStrPrefix + 'existingAttachments.plural', numOldAttachments);
}
var buttonFlags = (ps.BUTTON_POS_0) * (ps.BUTTON_TITLE_IS_STRING)
+ (ps.BUTTON_POS_1) * (ps.BUTTON_TITLE_CANCEL);
var index = ps.confirmEx(
null,
title,
(msg1 + msg2 + msg3).trim(),
buttonFlags,
Zotero.getString(chooseStrPrefix + 'button'),
null,
null,
null,
{}
);
if (index == 1) {
return false;
}
// Set new data directory
Zotero.debug("Setting new base directory");
Zotero.Prefs.set('baseAttachmentPath', newBasePathFile.persistentDescriptor);
Zotero.Prefs.set('saveRelativeAttachmentPath', true);
// Resave all attachments on base path (so that their paths become relative)
// and all other relative attachments (so that their paths become absolute)
for (let id in newAttachmentPaths) {
let attachment = Zotero.Items.get(id);
if (newAttachmentPaths[id]) {
attachment.attachmentPath = newAttachmentPaths[id];
attachment.save({
skipDateModifiedUpdate: true
});
}
else {
attachment.updateAttachmentPath();
}
}
return newBasePathFile.persistentDescriptor;
},
getPath: function (asFile) {
var desc = Zotero.Prefs.get('baseAttachmentPath');
if (desc == '') {
return asFile ? null : '';
}
var file = Components.classes["@mozilla.org/file/local;1"]
.createInstance(Components.interfaces.nsILocalFile);
try {
file.persistentDescriptor = desc;
}
catch (e) {
return asFile ? null : '';
}
return asFile ? file : file.path;
},
clearPath: function () {
// Find all current attachments with relative paths
var sql = "SELECT itemID FROM itemAttachments WHERE linkMode=? AND path LIKE '"
+ Zotero.Attachments.BASE_PATH_PLACEHOLDER + "%'";
var params = [Zotero.Attachments.LINK_MODE_LINKED_FILE];
var relativeAttachmentIDs = Zotero.DB.columnQuery(sql, params) || [];
// Prompt for confirmation
var ps = Components.classes["@mozilla.org/embedcomp/prompt-service;1"]
.getService(Components.interfaces.nsIPromptService);
var strPrefix = 'attachmentBasePath.clearBasePath.';
var title = Zotero.getString(strPrefix + 'title');
var msg = Zotero.getString(strPrefix + 'message');
switch (relativeAttachmentIDs.length) {
case 0:
break;
case 1:
msg += "\n\n" + Zotero.getString(strPrefix + 'existingAttachments.singular');
break;
default:
msg += "\n\n" + Zotero.getString(strPrefix + 'existingAttachments.plural',
relativeAttachmentIDs.length);
}
var buttonFlags = (ps.BUTTON_POS_0) * (ps.BUTTON_TITLE_IS_STRING)
+ (ps.BUTTON_POS_1) * (ps.BUTTON_TITLE_CANCEL);
var index = ps.confirmEx(
window,
title,
msg,
buttonFlags,
Zotero.getString(strPrefix + 'button'),
null,
null,
null,
{}
);
if (index == 1) {
return false;
}
// Disable relative path saving and then resave all relative
// attachments so that their absolute paths are stored
Zotero.debug('Clearing base directory');
Zotero.Prefs.set('saveRelativeAttachmentPath', false);
for (var i=0; i<relativeAttachmentIDs.length; i++) {
Zotero.Items.get(relativeAttachmentIDs[i]).updateAttachmentPath();
}
Zotero.Prefs.set('baseAttachmentPath', '');
},
updateUI: function () {
var filefield = document.getElementById('baseAttachmentPath');
var file = this.getPath(true);
filefield.file = file;
if (file) {
filefield.label = file.path;
}
else {
filefield.label = '';
}
document.getElementById('resetBasePath').disabled = !Zotero.Prefs.get('baseAttachmentPath');
}
};
Zotero_Preferences.Debug_Output = {
_timer: null,
init: function () {
var storing = Zotero.Debug.storing;
this._updateButton();
this.updateLines();
if (storing) {
this._initTimer();
}
},
toggleStore: function () {
this.setStore(!Zotero.Debug.storing);
},
setStore: function (set) {
Zotero.Debug.setStore(set);
if (set) {
this._initTimer();
}
else {
if (this._timerID) {
this._timer.cancel();
this._timerID = null;
}
}
this._updateButton();
this.updateLines();
},
view: function () {
Zotero_Preferences.openInViewer("zotero://debug/");
},
submit: function () {
document.getElementById('debug-output-submit').disabled = true;
document.getElementById('debug-output-submit-progress').hidden = false;
var url = "https://repo.zotero.org/repo/report?debug=1";
var output = Zotero.Debug.get(
Zotero.Prefs.get('debug.store.submitSize'),
Zotero.Prefs.get('debug.store.submitLineLength')
);
Zotero_Preferences.Debug_Output.setStore(false);
var uploadCallback = function (xmlhttp) {
document.getElementById('debug-output-submit').disabled = false;
document.getElementById('debug-output-submit-progress').hidden = true;
Zotero.debug(xmlhttp.responseText);
var ps = Components.classes["@mozilla.org/embedcomp/prompt-service;1"]
.getService(Components.interfaces.nsIPromptService);
if (!xmlhttp.responseXML) {
ps.alert(
null,
Zotero.getString('general.error'),
Zotero.getString('general.invalidResponseServer')
);
return;
}
var reported = xmlhttp.responseXML.getElementsByTagName('reported');
if (reported.length != 1) {
ps.alert(
null,
Zotero.getString('general.error'),
Zotero.getString('general.serverError')
);
return;
}
var reportID = reported[0].getAttribute('reportID');
ps.alert(
null,
Zotero.getString('zotero.preferences.advanced.debug.title'),
Zotero.getString('zotero.preferences.advanced.debug.sent', reportID)
);
}
var bufferUploader = function (data) {
var ps = Components.classes["@mozilla.org/embedcomp/prompt-service;1"]
.getService(Components.interfaces.nsIPromptService);
var oldLen = output.length;
var newLen = data.length;
var savings = Math.round(((oldLen - newLen) / oldLen) * 100)
Zotero.debug("HTTP POST " + newLen + " bytes to " + url
+ " (gzipped from " + oldLen + " bytes; "
+ savings + "% savings)");
if (Zotero.HTTP.browserIsOffline()) {
ps.alert(
null,
Zotero.getString('general.error'),
Zotero.getString('general.browserIsOffline', Zotero.appName)
);
return false;
}
var req =
Components.classes["@mozilla.org/xmlextras/xmlhttprequest;1"].
createInstance();
req.open('POST', url, true);
req.setRequestHeader('Content-Type', "text/plain");
req.setRequestHeader('Content-Encoding', 'gzip');
req.channel.notificationCallbacks = {
onProgress: function (request, context, progress, progressMax) {
var pm = document.getElementById('debug-output-submit-progress');
pm.mode = 'determined'
pm.value = progress;
pm.max = progressMax;
},
// nsIInterfaceRequestor
getInterface: function (iid) {
try {
return this.QueryInterface(iid);
}
catch (e) {
throw Components.results.NS_NOINTERFACE;
}
},
QueryInterface: function(iid) {
if (iid.equals(Components.interfaces.nsISupports) ||
iid.equals(Components.interfaces.nsIInterfaceRequestor) ||
iid.equals(Components.interfaces.nsIProgressEventSink)) {
return this;
}
throw Components.results.NS_NOINTERFACE;
},
}
req.onreadystatechange = function () {
if (req.readyState == 4) {
uploadCallback(req);
}
};
try {
req.sendAsBinary(data);
}
catch (e) {
ps.alert(
null,
Zotero.getString('general.error'),
Zotero.getString('zotero.preferences.advanced.debug.error')
);
}
}
// Get input stream from debug output data
var unicodeConverter =
Components.classes["@mozilla.org/intl/scriptableunicodeconverter"]
.createInstance(Components.interfaces.nsIScriptableUnicodeConverter);
unicodeConverter.charset = "UTF-8";
var bodyStream = unicodeConverter.convertToInputStream(output);
// Get listener for when compression is done
var listener = new Zotero.BufferedInputListener(bufferUploader);
// Initialize stream converter
var converter =
Components.classes["@mozilla.org/streamconv;1?from=uncompressed&to=gzip"]
.createInstance(Components.interfaces.nsIStreamConverter);
converter.asyncConvertData("uncompressed", "gzip", listener, null);
// Send input stream to stream converter
var pump = Components.classes["@mozilla.org/network/input-stream-pump;1"].
createInstance(Components.interfaces.nsIInputStreamPump);
pump.init(bodyStream, -1, -1, 0, 0, true);
pump.asyncRead(converter, null);
},
clear: function () {
Zotero.Debug.clear();
this.updateLines();
},
updateLines: function () {
var enabled = Zotero.Debug.storing;
var lines = Zotero.Debug.count();
document.getElementById('debug-output-lines').value = lines;
var empty = lines == 0;
document.getElementById('debug-output-view').disabled = !enabled && empty;
document.getElementById('debug-output-clear').disabled = empty;
document.getElementById('debug-output-submit').disabled = empty;
},
_initTimer: function () {
this._timer = Components.classes["@mozilla.org/timer;1"].
createInstance(Components.interfaces.nsITimer);
this._timer.initWithCallback({
notify: function() {
Zotero_Preferences.Debug_Output.updateLines();
}
}, 10000, Components.interfaces.nsITimer.TYPE_REPEATING_SLACK);
},
_updateButton: function () {
var storing = Zotero.Debug.storing
var button = document.getElementById('debug-output-enable');
if (storing) {
button.label = Zotero.getString('general.disable');
}
else {
button.label = Zotero.getString('general.enable');
}
},
onUnload: function () {
if (this._timer) {
this._timer.cancel();
}
}
};