Merge branch '4.0'

Conflicts:
	chrome/content/zotero/xpcom/zotero.js
	install.rdf
	update.rdf
This commit is contained in:
Simon Kornblith 2013-04-22 03:08:07 -04:00
commit db313abc73
41 changed files with 1431 additions and 925 deletions

View file

@ -47,7 +47,6 @@ locale zotero zh-TW chrome/locale/zh-TW/zotero/
skin zotero default chrome/skin/default/zotero/
overlay chrome://browser/content/browser.xul chrome://zotero/content/statusBarOverlay.xul appversion<4.0
overlay chrome://browser/content/browser.xul chrome://zotero/content/overlay.xul
overlay chrome://zotero/content/preferences/preferences.xul chrome://zotero/content/preferences/preferences_firefox.xul application={ec8030f7-c20a-464f-9b0e-13a3a9e97384}
@ -55,6 +54,7 @@ overlay chrome://zotero/content/preferences/preferences.xul#cite chrome://zotero
overlay chrome://zotero/content/preferences/preferences_general.xul chrome://zotero/content/preferences/preferences_general_firefox.xul application={ec8030f7-c20a-464f-9b0e-13a3a9e97384}
overlay chrome://zotero/content/preferences/preferences_export.xul chrome://zotero/content/preferences/preferences_export_firefox.xul application={ec8030f7-c20a-464f-9b0e-13a3a9e97384}
overlay chrome://zotero/content/preferences/preferences_advanced.xul chrome://zotero/content/preferences/preferences_advanced_firefox.xul application={ec8030f7-c20a-464f-9b0e-13a3a9e97384}
overlay chrome://zotero/content/preferences/preferences_advanced.xul chrome://zotero/content/preferences/preferences_advanced_standalone.xul application=zotero@chnm.gmu.edu
overlay chrome://mozapps/content/downloads/unknownContentType.xul chrome://zotero/content/downloadOverlay.xul

View file

@ -88,10 +88,10 @@ var Zotero_File_Interface_Bibliography = new function() {
}
// Has to be async to work properly
setTimeout(function () {
window.setTimeout(function () {
listbox.ensureIndexIsVisible(selectIndex);
listbox.selectedIndex = selectIndex;
});
}, 0);
// ONLY FOR bibliography.xul: export options
if(document.getElementById("save-as-rtf")) {
@ -119,8 +119,7 @@ var Zotero_File_Interface_Bibliography = new function() {
// bookmarks text
if(document.getElementById("displayAs")) {
if(_io.useEndnotes && _io.useEndnotes == 1) document.getElementById("displayAs").selectedIndex = 1;
styleChanged(selectIndex);
}
}
if(document.getElementById("formatUsing")) {
if(_io.fieldType == "Bookmark") document.getElementById("formatUsing").selectedIndex = 1;
var formatOption = (_io.primaryFieldType == "ReferenceMark" ? "referenceMarks" : "fields");

View file

@ -552,7 +552,7 @@
this._displayAllCreators = true;
if (this._addCreatorRow) {
this.addCreatorRow(false, false, true);
this.addCreatorRow(false, this.item.getCreator(max-1).creatorTypeID, true);
this._addCreatorRow = false;
this.disableCreatorAddButtons();
}
@ -1416,11 +1416,17 @@
|| fieldName == 'creator') {
t.setAttribute('type', 'autocomplete');
t.setAttribute('autocompletesearch', 'zotero');
var suffix = itemID ? itemID : '';
if (field=='creator') {
suffix = elem.getAttribute('fieldMode') + '-' + suffix;
}
t.setAttribute('autocompletesearchparam', fieldName + '/' + suffix);
let params = {
fieldName: fieldName,
libraryID: this.item.libraryID
};
if (field == 'creator') {
params.fieldMode = parseInt(elem.getAttribute('fieldMode'));
params.itemID = itemID ? itemID : '';
};
t.setAttribute(
'autocompletesearchparam', JSON.stringify(params)
);
t.setAttribute('ontextentered',
'document.getBindingParent(this).handleCreatorAutoCompleteSelect(this)');
}
@ -1555,8 +1561,8 @@
this._focusNextField(this._dynamicFields, this._lastTabIndex, false);
}
else {
// TODO: should use current creator type
this.addCreatorRow(false, false, true);
var creatorFields = this.getCreatorFields(Zotero.getAncestorByTagName(target, 'row'));
this.addCreatorRow(false, creatorFields.creatorTypeID, true);
}
}
// Value has changed

View file

@ -437,8 +437,14 @@
else {
t.setAttribute('type', 'autocomplete');
t.setAttribute('autocompletesearch', 'zotero');
var suffix = itemID ? itemID : '';
t.setAttribute('autocompletesearchparam', fieldName + '/' + suffix);
let params = {
fieldName: fieldName,
libraryID: this.item.libraryID
};
params.itemID = itemID ? itemID : '';
t.setAttribute(
'autocompletesearchparam', JSON.stringify(params)
);
}
var box = elem.parentNode;

View file

@ -813,22 +813,20 @@
textbox.setAttribute('autocompletesearch', 'zotero');
textbox.setAttribute('timeout', '250');
if (condition=='creator')
{
// 2 searches both single- and double-field creators
var autocompleteCondition = condition + '/2'
var autocompleteParams = {
fieldName: condition
};
if (condition == 'creator') {
autocompleteParams.fieldMode = 2;
}
else
{
var autocompleteCondition = condition;
}
textbox.setAttribute('autocompletesearchparam', autocompleteCondition);
textbox.setAttribute(
'autocompletesearchparam',
JSON.stringify(autocompleteParams)
);
}
}
if (!autocompleteCondition)
{
if (!autocompleteParams) {
var textbox = document.getAnonymousNodes(this)[0];
textbox.removeAttribute('type');
}

View file

@ -804,16 +804,23 @@ Zotero_Browser.Tab.prototype._selectItems = function(obj, itemList, callback) {
*/
Zotero_Browser.Tab.prototype._translatorsAvailable = function(translate, translators) {
if(translators && translators.length) {
// if there's already a scrapable page in the browser window, and it's
// still there, ensure it is actually part of the page, then return
if(this.page.translators && this.page.translators.length && this.page.document.location) {
if(this.page.document.defaultView && !this.page.document.defaultView.closed
&& this.page.document.location.href != translate.document.location.href) {
// if it is still there, switch translation to take place on
if(!translators.length || this.page.translators[0].priority <= translators[0].priority) return;
} else {
this.clear();
}
//see if we should keep the previous set of translators
if(//we already have a translator for part of this page
this.page.translators && this.page.translators.length && this.page.document.location
//and the page is still there
&& this.page.document.defaultView && !this.page.document.defaultView.closed
//this set of translators is not targeting the same URL as a previous set of translators,
// because otherwise we want to use the newer set
&& this.page.document.location.href != translate.document.location.href
//the previous set of translators targets the top frame or the current one does not either
&& (this.page.document.defaultView == this.page.document.defaultView.top
|| translate.document.defaultView !== this.page.document.defaultView.top)
//the best translator we had was of higher priority than the new set
&& this.page.translators[0].priority <= translators[0].priority
) {
return; //keep what we had
} else {
this.clear(); //clear URL bar icon
}
this.page.translate = translate;

@ -1 +1 @@
Subproject commit 5b7a687df6464af87eaacc4088bd136ec1039d1b
Subproject commit 007de1a82c0359e897610d67edd11e0086f48689

View file

@ -364,22 +364,30 @@ Zotero_Preferences.Attachment_Base_Directory = {
.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);
attachmentFile.persistentDescriptor = attachment.attachmentPath;
// 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
let isExistingRelativeAttachment = oldRelativeAttachmentIDs.indexOf(attachmentID) != -1;
if (isExistingRelativeAttachment && oldBasePathFile) {
let relFile = attachmentFile.clone();
let relPath = attachmentFile.getRelativeDescriptor(oldBasePathFile);
if (relPath) {
let relFile = Components.classes["@mozilla.org/file/local;1"]
.createInstance(Components.interfaces.nsILocalFile);
relFile.setRelativeDescriptor(newBasePathFile, relPath);
if (relFile.exists()) {
numNewAttachments++;
@ -390,14 +398,14 @@ Zotero_Preferences.Attachment_Base_Directory = {
// 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 (Zotero.File.directoryContains(newBasePathFile, attachmentFile)) {
newAttachmentPaths[attachmentID] = isExistingRelativeAttachment
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 (isExistingRelativeAttachment && oldBasePathFile) {
else if (relPath && oldBasePathFile) {
newAttachmentPaths[attachmentID] = attachmentFile.persistentDescriptor;
numOldAttachments++;
}
@ -464,7 +472,9 @@ Zotero_Preferences.Attachment_Base_Directory = {
let attachment = Zotero.Items.get(id);
if (newAttachmentPaths[id]) {
attachment.attachmentPath = newAttachmentPaths[id];
attachment.save();
attachment.save({
skipDateModifiedUpdate: true
});
}
else {
attachment.updateAttachmentPath();

View file

@ -0,0 +1,36 @@
<?xml version="1.0"?>
<!--
***** BEGIN LICENSE BLOCK *****
Copyright © 2013 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 *****
-->
<!DOCTYPE prefwindow SYSTEM "chrome://zotero/locale/preferences.dtd">
<overlay xmlns="http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul">
<groupbox id="zotero-prefpane-advanced-miscellaneous">
<hbox id="zotero-standalone-buttons">
<button id="openAboutMemory"
label="&zotero.preferences.openAboutMemory;"
oncommand="Zotero_Preferences.openInViewer('about:memory')"/>
</hbox>
</groupbox>
</overlay>

View file

@ -72,7 +72,7 @@ Zotero_Preferences.Sync = {
}
if (oldProtocol == 'zotero' && protocol == 'webdav') {
var sql = "SELECT COUNT(*) FROM version WHERE schema='storage_zfs'";
var sql = "SELECT COUNT(*) FROM version WHERE schema LIKE 'storage_zfs%'";
if (Zotero.DB.valueQuery(sql)) {
var ps = Components.classes["@mozilla.org/embedcomp/prompt-service;1"]
.getService(Components.interfaces.nsIPromptService);

View file

@ -529,13 +529,15 @@ var Zotero_RTFScan = new function() {
itemIDs = [itemID for(itemID in itemIDs)];
Zotero.debug(itemIDs);
style.updateItems(itemIDs);
// prepare the list of rendered citations
var citationResults = style.rebuildProcessorState(cslCitations, "rtf");
// format citations
var contentArray = [];
var lastEnd = 0;
for(var i=0; i<citations.length; i++) {
var citation = style.appendCitationCluster(cslCitations[i], true)[0][1];
var citation = citationResults[i][2];
Zotero.debug("Formatted "+citation);
// if using notes, we might have to move the note after the punctuation

View file

@ -334,7 +334,9 @@ Zotero_TranslatorTester.prototype._runTestsRecursively = function(testDoneCallba
if(this.type === "web") {
this.fetchPageAndRunTest(test, callback);
} else {
this.runTest(test, null, callback);
(Zotero.setTimeout ? Zotero : window).setTimeout(function() {
me.runTest(test, null, callback);
}, 0);
}
(Zotero.setTimeout ? Zotero : window).setTimeout(function() {

View file

@ -50,13 +50,7 @@ Zotero.Attachments = new function(){
function importFromFile(file, sourceItemID, libraryID) {
Zotero.debug('Importing attachment from file');
// Try decoding URI entities, since we're going to strip '%'
var newName = file.leafName;
try {
newName = decodeURIComponent(file.leafName);
}
catch (e) {}
newName = Zotero.File.getValidFileName(newName);
var newName = Zotero.File.getValidFileName(file.leafName);
if (!file.isFile()) {
throw ("'" + file.leafName + "' must be a file in Zotero.Attachments.importFromFile()");
@ -82,14 +76,15 @@ Zotero.Attachments = new function(){
// Create directory for attachment files within storage directory
var destDir = this.createDirectoryForItem(itemID);
file.copyTo(destDir, newName);
// Point to copied file
var newFile = destDir.clone();
newFile.append(newName);
var mimeType = Zotero.MIME.getMIMETypeFromFile(newFile);
// Copy file to unique filename, which automatically shortens long filenames
newFile = Zotero.File.copyToUnique(file, newFile);
var mimeType = Zotero.MIME.getMIMETypeFromFile(newFile);
attachmentItem.attachmentMIMEType = mimeType;
attachmentItem.attachmentPath = this.getPath(newFile, this.LINK_MODE_IMPORTED_FILE);
@ -1018,6 +1013,104 @@ Zotero.Attachments = new function(){
}
/**
* If file is within the attachment base directory, return a relative
* path prefixed by BASE_PATH_PLACEHOLDER. Otherwise, return unchanged.
*/
this.getBaseDirectoryRelativePath = function (path) {
if (!path || path.indexOf(this.BASE_PATH_PLACEHOLDER) == 0) {
return path;
}
var basePath = Zotero.Prefs.get('baseAttachmentPath');
if (!basePath) {
return path;
}
// Get nsIFile for base directory
var baseDir = Components.classes["@mozilla.org/file/local;1"]
.createInstance(Components.interfaces.nsILocalFile);
try {
baseDir.persistentDescriptor = basePath;
}
catch (e) {
Zotero.debug(e, 1);
Components.utils.reportError(e);
return path;
}
// Get nsIFile for file
var attachmentFile = Components.classes["@mozilla.org/file/local;1"]
.createInstance(Components.interfaces.nsILocalFile);
try {
attachmentFile.persistentDescriptor = path;
}
catch (e) {
Zotero.debug(e, 1);
Components.utils.reportError(e);
return path;
}
if (Zotero.File.directoryContains(baseDir, attachmentFile)) {
path = this.BASE_PATH_PLACEHOLDER
+ attachmentFile.getRelativeDescriptor(baseDir);
}
return path;
}
/**
* Get a file from this path, if we can
*
* @param {String} path Absolute path or relative path prefixed
* by BASE_PATH_PLACEHOLDER
* @param {Boolean} asFile Return nsIFile instead of path
* @return {String|nsIFile|FALSE} Persistent descriptor string, file,
* of FALSE if no path
*/
this.resolveRelativePath = function (path) {
if (path.indexOf(Zotero.Attachments.BASE_PATH_PLACEHOLDER) != 0) {
return false;
}
var basePath = Zotero.Prefs.get('baseAttachmentPath');
if (!basePath) {
Zotero.debug("No base attachment path set -- can't resolve '" + path + "'", 2);
return false;
}
// Get file from base directory
var baseDir = Components.classes["@mozilla.org/file/local;1"]
.createInstance(Components.interfaces.nsILocalFile);
try {
baseDir.persistentDescriptor = basePath;
}
catch (e) {
Zotero.debug(e, 1);
Components.utils.reportError(e);
Zotero.debug("Invalid base attachment path -- can't resolve'" + row.path + "'", 2);
return false;
}
// Get file from relative path
var relativePath = path.substr(
Zotero.Attachments.BASE_PATH_PLACEHOLDER.length
);
var file = Components.classes["@mozilla.org/file/local;1"]
.createInstance(Components.interfaces.nsILocalFile);
try {
file.setRelativeDescriptor(baseDir, relativePath);
}
catch (e) {
Zotero.debug("Invalid relative descriptor '" + relativePath + "'", 2);
return false;
}
return file;
}
/**
* Returns the number of files in the attachment directory
*
@ -1394,6 +1487,7 @@ Zotero.Attachments = new function(){
*/
this.isPDFJS = function(doc) {
// pdf.js HACK
// This may no longer be necessary (as of Fx 23)
if(doc.contentType === "text/html") {
var win = doc.defaultView;
if(win) {

File diff suppressed because it is too large Load diff

View file

@ -59,7 +59,14 @@ Zotero.Connector = new function() {
var xdr = new XDomainRequest();
xdr.timeout = 700;
xdr.open("POST", "http://127.0.0.1:23119/connector/ping", true);
xdr.onerror = xdr.ontimeout = fail
xdr.onerror = function() {
Zotero.debug("Connector: XDomainRequest to Zotero Standalone experienced an error");
fail();
};
xdr.ontimeout = function() {
Zotero.debug("Connector: XDomainRequest to Zotero Standalone timed out");
fail();
};
xdr.onload = function() {
if(me.isOnline !== null) return;
me.isOnline = true;
@ -67,7 +74,8 @@ Zotero.Connector = new function() {
_ieConnectorCallbacks = [];
var listener = function(event) {
if(event.origin !== "http://127.0.0.1:23119") return;
if(event.origin !== "http://127.0.0.1:23119"
|| event.source !== iframe.contentWindow) return;
if(event.stopPropagation) {
event.stopPropagation();
} else {

View file

@ -76,7 +76,6 @@ Zotero.Item.prototype._init = function () {
this._changedSource = false;
this._changedAttachmentData = false;
this._skipModTimeUpdate = false;
this._previousData = {};
this._bestAttachmentState = null;
@ -1251,7 +1250,11 @@ Zotero.Item.prototype.removeRelatedItem = function (itemID) {
*
* Returns true on item update or itemID of new item
*/
Zotero.Item.prototype.save = function() {
Zotero.Item.prototype.save = function(options) {
if (!options) {
options = {};
}
Zotero.Items.editCheck(this);
if (!this.hasChanged()) {
@ -1527,37 +1530,16 @@ Zotero.Item.prototype.save = function() {
var path = this.attachmentPath;
var syncState = this.attachmentSyncState;
// Save attachment within attachment base directory as relative path
if (this.attachmentLinkMode == Zotero.Attachments.LINK_MODE_LINKED_FILE && path) {
let basePath = Zotero.Prefs.get('baseAttachmentPath');
if (basePath != '' && Zotero.Prefs.get('saveRelativeAttachmentPath')) {
let baseDir = Components.classes["@mozilla.org/file/local;1"]
.createInstance(Components.interfaces.nsILocalFile);
try {
baseDir.persistentDescriptor = basePath;
}
catch (e) {
Zotero.debug(e, 1);
Components.utils.reportError(e);
baseDir = null;
}
if (baseDir) {
let attachmentFile = Components.classes["@mozilla.org/file/local;1"]
.createInstance(Components.interfaces.nsILocalFile);
try {
attachmentFile.persistentDescriptor = path;
}
catch (e) {
Zotero.debug(e, 1);
Components.utils.reportError(e);
attachmentFile = null;
}
if (attachmentFile && Zotero.File.directoryContains(baseDir, attachmentFile)) {
path = Zotero.Attachments.BASE_PATH_PLACEHOLDER
+ attachmentFile.getRelativeDescriptor(baseDir);
}
if (this.attachmentLinkMode == Zotero.Attachments.LINK_MODE_LINKED_FILE) {
// Save attachment within attachment base directory as relative path
if (Zotero.Prefs.get('saveRelativeAttachmentPath')) {
path = Zotero.Attachments.getBaseDirectoryRelativePath(path);
}
// If possible, convert relative path to absolute
else {
let file = Zotero.Attachments.resolveRelativePath(path);
if (file) {
path = file.persistentDescriptor;
}
}
}
@ -1669,8 +1651,11 @@ Zotero.Item.prototype.save = function() {
sql += field + '=?, ';
sqlValues.push(this.getField(field));
}
else if ((field == 'dateModified' || field == 'clientDateModified')
&& !this._skipModTimeUpdate) {
else if (field == 'dateModified' && !options.skipDateModifiedUpdate) {
sql += field + '=?, ';
sqlValues.push(Zotero.DB.transactionDateTime);
}
else if (field == 'clientDateModified' && !options.skipClientDateModifiedUpdate) {
sql += field + '=?, ';
sqlValues.push(Zotero.DB.transactionDateTime);
}
@ -1962,37 +1947,16 @@ Zotero.Item.prototype.save = function() {
var path = this.attachmentPath;
var syncState = this.attachmentSyncState;
// Save attachment within attachment base directory as relative path
if (this.attachmentLinkMode == Zotero.Attachments.LINK_MODE_LINKED_FILE && path) {
let basePath = Zotero.Prefs.get('baseAttachmentPath');
if (basePath != '' && Zotero.Prefs.get('saveRelativeAttachmentPath')) {
let baseDir = Components.classes["@mozilla.org/file/local;1"]
.createInstance(Components.interfaces.nsILocalFile);
try {
baseDir.persistentDescriptor = basePath;
}
catch (e) {
Zotero.debug(e, 1);
Components.utils.reportError(e);
baseDir = null;
}
if (baseDir) {
let attachmentFile = Components.classes["@mozilla.org/file/local;1"]
.createInstance(Components.interfaces.nsILocalFile);
try {
attachmentFile.persistentDescriptor = path;
}
catch (e) {
Zotero.debug(e, 1);
Components.utils.reportError(e);
attachmentFile = null;
}
if (attachmentFile && Zotero.File.directoryContains(baseDir, attachmentFile)) {
path = Zotero.Attachments.BASE_PATH_PLACEHOLDER
+ attachmentFile.getRelativeDescriptor(baseDir);
}
if (this.attachmentLinkMode == Zotero.Attachments.LINK_MODE_LINKED_FILE) {
// Save attachment within attachment base directory as relative path
if (Zotero.Prefs.get('saveRelativeAttachmentPath')) {
path = Zotero.Attachments.getBaseDirectoryRelativePath(path);
}
// If possible, convert relative path to absolute
else {
let file = Zotero.Attachments.resolveRelativePath(path);
if (file) {
path = file.persistentDescriptor;
}
}
}
@ -2864,6 +2828,7 @@ Zotero.Item.prototype.getFile = function(row, skipExistsCheck) {
return false;
}
// Imported file with relative path
if (row.linkMode == Zotero.Attachments.LINK_MODE_IMPORTED_URL ||
row.linkMode == Zotero.Attachments.LINK_MODE_IMPORTED_FILE) {
try {
@ -2913,6 +2878,15 @@ Zotero.Item.prototype.getFile = function(row, skipExistsCheck) {
}
}
}
// Linked file with relative path
else if (row.linkMode == Zotero.Attachments.LINK_MODE_LINKED_FILE &&
row.path.indexOf(Zotero.Attachments.BASE_PATH_PLACEHOLDER) == 0) {
var file = Zotero.Attachments.resolveRelativePath(row.path);
if (!file) {
updateAttachmentStates(false);
return false;
}
}
else {
var file = Components.classes["@mozilla.org/file/local;1"].
createInstance(Components.interfaces.nsILocalFile);
@ -3073,11 +3047,10 @@ Zotero.Item.prototype.relinkAttachmentFile = function(file, skipItemUpdate) {
var path = Zotero.Attachments.getPath(file, linkMode);
this.attachmentPath = path;
if (skipItemUpdate) {
this._skipModTimeUpdate = true;
}
this.save();
this._skipModTimeUpdate = false;
this.save({
skipDateModifiedUpdate: true,
skipClientDateModifiedUpdate: skipItemUpdate
});
return false;
}
@ -3274,58 +3247,20 @@ Zotero.Item.prototype.__defineGetter__('attachmentPath', function () {
return undefined;
}
var pathIsRelative = false;
if (this._attachmentPath !== null) {
pathIsRelative = this._attachmentPath.indexOf(Zotero.Attachments.BASE_PATH_PLACEHOLDER) == 0
&& this.attachmentLinkMode == Zotero.Attachments.LINK_MODE_LINKED_FILE;
if (!pathIsRelative) {
return this._attachmentPath;
}
}
else if (!this.id) {
return this._attachmentPath;
}
if (!this.id) {
return '';
}
else {
var sql = "SELECT path FROM itemAttachments WHERE itemID=?";
var path = Zotero.DB.valueQuery(sql, this.id);
if (!path) {
this._attachmentPath = '';
return this._attachmentPath;
}
this._attachmentPath = path;
pathIsRelative = path.indexOf(Zotero.Attachments.BASE_PATH_PLACEHOLDER) == 0
&& this.attachmentLinkMode == Zotero.Attachments.LINK_MODE_LINKED_FILE;
}
if (pathIsRelative) {
var basePath = Zotero.Prefs.get('baseAttachmentPath');
// If the base path has been cleared, don't try to recreate the full attachment path
if (basePath == '') {
return '';
}
var baseDir = Components.classes["@mozilla.org/file/local;1"]
.createInstance(Components.interfaces.nsILocalFile);
try {
baseDir.persistentDescriptor = basePath;
}
catch (e) {
Zotero.debug(e, 1);
Components.utils.reportError(e);
return '';
}
var relativePath = this._attachmentPath.substr(
Zotero.Attachments.BASE_PATH_PLACEHOLDER.length
);
var attachmentFile = Components.classes["@mozilla.org/file/local;1"]
.createInstance(Components.interfaces.nsILocalFile);
attachmentFile.setRelativeDescriptor(baseDir,relativePath);
return attachmentFile.persistentDescriptor;
var sql = "SELECT path FROM itemAttachments WHERE itemID=?";
var path = Zotero.DB.valueQuery(sql, this.id);
if (!path) {
path = '';
}
this._attachmentPath = path;
return path;
});
@ -3366,7 +3301,9 @@ Zotero.Item.prototype.updateAttachmentPath = function () {
this._changedAttachmentData = {};
}
this._changedAttachmentData.path = true;
this.save();
this.save({
skipDateModifiedUpdate: true
});
};

View file

@ -27,7 +27,7 @@
Zotero.Notes = new function() {
this.noteToTitle = noteToTitle;
this.__defineGetter__("MAX_TITLE_LENGTH", function() { return 80; });
this.__defineGetter__("MAX_TITLE_LENGTH", function() { return 120; });
this.__defineGetter__("defaultNote", function () '<div class="zotero-note znv1"></div>');
this.__defineGetter__("notePrefix", function () '<div class="zotero-note znv1">');
this.__defineGetter__("noteSuffix", function () '</div>');

View file

@ -39,7 +39,6 @@ Zotero.File = new function(){
this.putContents = putContents;
this.getValidFileName = getValidFileName;
this.truncateFileName = truncateFileName;
this.copyToUnique = this.copyToUnique;
this.getCharsetFromFile = getCharsetFromFile;
this.addCharsetListener = addCharsetListener;
@ -287,14 +286,14 @@ Zotero.File = new function(){
}
function copyToUnique(file, newFile) {
this.copyToUnique = function (file, newFile) {
newFile.createUnique(Components.interfaces.nsIFile.NORMAL_FILE_TYPE, 0644);
var newName = newFile.leafName;
newFile.remove(null);
// Copy file to unique name
file.copyTo(newFile.parent, newName);
return file;
return newFile;
}
@ -361,7 +360,7 @@ Zotero.File = new function(){
function getValidFileName(fileName, skipXML) {
// TODO: use space instead, and figure out what's doing extra
// URL encode when saving attachments that trigger this
fileName = fileName.replace(/[\/\\\?%\*:|"<>]/g, '');
fileName = fileName.replace(/[\/\\\?\*:|"<>]/g, '');
// Replace newlines and tabs (which shouldn't be in the string in the first place) with spaces
fileName = fileName.replace(/[\r\n\t]+/g, ' ');
// Replace various thin spaces

View file

@ -575,8 +575,14 @@ Zotero.Fulltext = new function(){
flags += 'i';
}
var re = new RegExp(searchText, flags);
var matches = re(str);
try {
var re = new RegExp(searchText, flags);
var matches = re.exec(str);
}
catch (e) {
Zotero.debug(e, 1);
Components.utils.reportError(e);
}
if (matches){
Zotero.debug("Text found");
return str.substr(matches.index, 50);

View file

@ -57,8 +57,11 @@ Zotero.MIMETypeHandler = new function () {
if(Zotero.Prefs.get("parseEndNoteMIMETypes")) {
this.addHandler("application/x-endnote-refer", _importHandler, true);
this.addHandler("application/x-research-info-systems", _importHandler, true);
// Add ISI
this.addHandler("application/x-inst-for-scientific-info", _importHandler, true);
this.addHandler("text/x-bibtex", _importHandler, true);
this.addHandler("application/x-bibtex", _importHandler, true);
//
// And some non-standard ones
//

View file

@ -31,8 +31,8 @@ Zotero.Schema = new function(){
var _dbVersions = [];
var _schemaVersions = [];
var _repositoryTimer;
var _remoteUpdateInProgress = false,
_localUpdateInProgress = false;
var _remoteUpdateInProgress = false, _localUpdateInProgress = false;
var _renamedStylesByNew = null;
var self = this;
@ -597,6 +597,8 @@ Zotero.Schema = new function(){
// Delete renamed/obsolete files
case 'chicago-note.csl':
case 'mhra_note_without_bibliography.csl':
case 'mhra.csl':
case 'mla.csl':
toDelete.push(file);
continue;
@ -1714,6 +1716,7 @@ Zotero.Schema = new function(){
xmlnode.normalize();
var uri = xmlnode.getAttribute('id');
var shortName = uri.replace("http://www.zotero.org/styles/", "");
// Delete local style if CSL code is empty
if (!xmlnode.firstChild) {
@ -1724,18 +1727,10 @@ Zotero.Schema = new function(){
return;
}
// Remove renamed styles
if (uri == 'http://www.zotero.org/styles/american-medical-association') {
var oldID = 'http://www.zotero.org/styles/ama';
var style = Zotero.Styles.get(oldID);
if (style && style.file.exists()) {
Zotero.debug("Deleting renamed style '" + oldID + "'");
style.file.remove(false);
}
}
else if (uri == 'http://www.zotero.org/styles/national-library-of-medicine') {
var oldID = 'http://www.zotero.org/styles/nlm';
var style = Zotero.Styles.get(oldID);
// Remove renamed styles, as instructed by the server
var oldID = xmlnode.getAttribute('oldID');
if (oldID) {
var style = Zotero.Styles.get(oldID, true);
if (style && style.file.exists()) {
Zotero.debug("Deleting renamed style '" + oldID + "'");
style.file.remove(false);

View file

@ -306,7 +306,8 @@ Zotero.Server.DataListener.prototype._generateResponse = function(status, conten
if(!Zotero.isServer) {
response += "X-Zotero-Version: "+Zotero.version+"\r\n";
response += "X-Zotero-Connector-API-Version: "+CONNECTOR_API_VERSION+"\r\n";
if(this.origin === "https://www.zotero.org" || this.origin === "http://www.zotero.org") {
if(this.origin === ZOTERO_CONFIG.BOOKMARKLET_ORIGIN ||
this.origin === ZOTERO_CONFIG.HTTP_BOOKMARKLET_ORIGIN) {
response += "Access-Control-Allow-Origin: "+this.origin+"\r\n";
response += "Access-Control-Allow-Methods: POST, GET, OPTIONS\r\n";
response += "Access-Control-Allow-Headers: Content-Type,X-Zotero-Connector-API-Version,X-Zotero-Version\r\n";

View file

@ -55,6 +55,14 @@ Zotero.Server.Connector.AttachmentProgressManager = new function() {
this.getProgressForID = function(progressID) {
return progressID in attachmentProgress ? attachmentProgress[progressID] : 0;
};
/**
* Check if we have received progress for a given attachment
*/
this.has = function(attachment) {
return attachmentsInProgress.has(attachment)
&& attachmentsInProgress.get(attachment) in attachmentProgress;
}
};
/**
@ -285,7 +293,6 @@ Zotero.Server.Connector.SavePage.prototype = {
Zotero.Server.Connector.AttachmentProgressManager.onProgress(attachment, progress, error);
});
translate.setHandler("itemsDone", function(obj, item) {
Zotero.Server.Connector.AttachmentProgressManager.add(item.attachments);
Zotero.Browser.deleteHiddenBrowser(me._browser);
if(jsonItems.length || me.selectedItems === false) {
me.sendResponse(201, "application/json", JSON.stringify({"items":jsonItems}));
@ -340,11 +347,21 @@ Zotero.Server.Connector.SaveItem.prototype = {
// save items
var itemSaver = new Zotero.Translate.ItemSaver(libraryID,
Zotero.Translate.ItemSaver.ATTACHMENT_MODE_DOWNLOAD, 1, undefined, cookieSandbox);
itemSaver.saveItems(data.items, function(returnValue, newItems) {
itemSaver.saveItems(data.items, function(returnValue, items) {
if(returnValue) {
try {
for each(var item in newItems) {
if(collection) collection.addItem(item.id);
// Remove attachments not being saved from item.attachments
for(var i=0; i<data.items.length; i++) {
var item = data.items[i];
for(var j=0; j<item.attachments.length; j++) {
if(!Zotero.Server.Connector.AttachmentProgressManager.has(item.attachments[j])) {
item.attachments.splice(j--, 1);
}
}
}
for(var i=0; i<items.length; i++) {
if(collection) collection.addItem(items[i].id);
}
sendResponseCallback(201, "application/json", JSON.stringify({"items":data.items}));

View file

@ -242,7 +242,7 @@ Zotero.Sync.Storage = new function () {
);
if (version == lastSyncTime) {
Zotero.debug("Last " + libraryModes[libraryID].name
+ " sync time hasn't changed for library "
+ " sync id hasn't changed for library "
+ libraryID + " -- skipping file downloads");
downloadAll = false;
}

View file

@ -314,7 +314,7 @@ Zotero.Sync.Storage.Request.prototype.stop = function (force) {
this._forceFinish = true;
}
if (this.channel) {
if (this.channel && this.channel.isPending()) {
this._stopping = true;
try {

View file

@ -33,6 +33,8 @@ Zotero.Sync.Storage.WebDAV = (function () {
var _loginManagerHost = 'chrome://zotero';
var _loginManagerURL = 'Zotero Storage Server';
var _lastSyncIDLength = 30;
//
// Private methods
//
@ -983,89 +985,116 @@ Zotero.Sync.Storage.WebDAV = (function () {
obj._getLastSyncTime = function () {
var lastSyncURI = this.rootURI;
lastSyncURI.spec += "lastsync.txt";
// Cache the credentials at the root URI
var self = this;
return Q.fcall(function () {
return self._cacheCredentials();
})
.then(function () {
var lastSyncURI = self.rootURI;
.then(function () {
return Zotero.HTTP.promise("GET", lastSyncURI,
{ debug: true, successCodes: [200, 404] });
})
.then(function (req) {
if (req.status == 404) {
Zotero.debug("No last WebDAV sync file");
// If no lastsync.txt, check previously used 'lastsync',
// and then delete it
let lastSyncURI = self.rootURI;
lastSyncURI.spec += "lastsync";
return Zotero.HTTP.promise("GET", lastSyncURI,
{ debug: true, successCodes: [200, 404] });
})
.then(function (req) {
if (req.status == 404) {
Zotero.debug("No last WebDAV sync time");
return null;
}
var lastModified = req.getResponseHeader("Last-Modified");
var date = new Date(lastModified);
Zotero.debug("Last successful WebDAV sync was " + date);
return Zotero.Date.toUnixTimestamp(date);
})
.fail(function (e) {
if (e instanceof Zotero.HTTP.UnexpectedStatusException) {
if (e.status == 403) {
Zotero.debug("Clearing WebDAV authentication credentials", 2);
_cachedCredentials = false;
}
else {
throw("HTTP " + e.status + " error from WebDAV server "
+ "for GET request");
{ debug: true, successCodes: [200, 404] })
.then(function (req) {
if (req.status == 404) {
return null;
}
return Q.reject(e);
Zotero.HTTP.promise("DELETE", lastSyncURI,
{ debug: true, successCodes: [200, 204, 404] })
.done();
var lastModified = req.getResponseHeader("Last-Modified");
var date = new Date(lastModified);
Zotero.debug("Last successful WebDAV sync was " + date);
return Zotero.Date.toUnixTimestamp(date);
});
}
var lastModified = req.getResponseHeader("Last-Modified");
var date = new Date(lastModified);
Zotero.debug("Last successful WebDAV sync was " + date);
var re = new RegExp("^[a-zA-Z0-9]{" + _lastSyncIDLength + "}$");
if (!re.test(req.responseText)) {
Zotero.HTTP.promise("DELETE", lastSyncURI,
{ debug: true, successCodes: [200, 204, 404] })
.done();
throw new Error("Invalid last sync id '" + req.responseText+ "'")
}
return req.responseText;
})
.catch(function (e) {
if (e instanceof Zotero.HTTP.UnexpectedStatusException) {
if (e.status == 403) {
Zotero.debug("Clearing WebDAV authentication credentials", 2);
_cachedCredentials = false;
}
// TODO: handle browser offline exception
else {
throw (e);
throw("HTTP " + e.status + " error from WebDAV server "
+ "for GET request");
}
});
return Q.reject(e);
}
// TODO: handle browser offline exception
else {
throw (e);
}
});
};
obj._setLastSyncTime = function (libraryID, localLastSyncTime) {
obj._setLastSyncTime = function (libraryID, localLastSyncID) {
if (libraryID) {
throw new Error("libraryID must be 0");
}
// DEBUG: is this necessary for WebDAV?
if (localLastSyncTime) {
if (localLastSyncID) {
var sql = "REPLACE INTO version VALUES (?, ?)";
Zotero.DB.query(
sql, ['storage_webdav_' + libraryID, { int: localLastSyncTime }]
sql, ['storage_webdav_' + libraryID, localLastSyncID]
);
return;
}
var uri = this.rootURI;
var successFileURI = uri.clone();
successFileURI.spec += "lastsync";
successFileURI.spec += "lastsync.txt";
var self = this;
// Generate a random id for the last-sync id
var id = Zotero.Utilities.randomString(_lastSyncIDLength);
return Zotero.HTTP.promise("PUT", successFileURI, " ",
{ debug: true, successCodes: [200, 201, 204] })
.then(function () {
return self._getLastSyncTime()
.then(function (ts) {
if (ts) {
var sql = "REPLACE INTO version VALUES (?, ?)";
Zotero.DB.query(
sql, ['storage_webdav_' + libraryID, { int: ts }]
);
}
});
})
.catch(function (e) {
var msg = "HTTP " + req.status + " error from WebDAV server "
+ "for PUT request";
Zotero.debug(msg, 2);
Components.utils.reportError(msg);
throw Zotero.Sync.Storage.WebDAV.defaultError;
});
return Zotero.HTTP.promise("PUT", successFileURI,
{ body: id, debug: true, successCodes: [200, 201, 204] })
.then(function () {
var sql = "REPLACE INTO version VALUES (?, ?)";
Zotero.DB.query(
sql, ['storage_webdav_' + libraryID, id]
);
})
.catch(function (e) {
var msg = "HTTP " + req.status + " error from WebDAV server "
+ "for PUT request";
Zotero.debug(msg, 2);
Components.utils.reportError(msg);
throw Zotero.Sync.Storage.WebDAV.defaultError;
});
};
@ -1182,7 +1211,7 @@ Zotero.Sync.Storage.WebDAV = (function () {
case 207:
// Test if Zotero directory is writable
var testFileURI = uri.clone();
testFileURI.spec += "zotero-test-file";
testFileURI.spec += "zotero-test-file.prop";
Zotero.HTTP.WebDAV.doPut(testFileURI, " ", function (req) {
Zotero.debug(req.responseText);
Zotero.debug(req.status);
@ -1235,7 +1264,7 @@ Zotero.Sync.Storage.WebDAV = (function () {
// data stores.
//
// This can also be from IIS 6+, which is configured
// not to serve extensionless files or .prop files
// not to serve .prop files.
// http://support.microsoft.com/kb/326965
case 404:
return deferred.resolve([uri, Zotero.Sync.Storage.ERROR_FILE_MISSING_AFTER_UPLOAD]);

View file

@ -1043,6 +1043,10 @@ Zotero.Sync.Storage.ZFS = (function () {
*/
obj._purgeDeletedStorageFiles = function () {
return Q.fcall(function () {
// Cache the credentials at the root
return this._cacheCredentials();
}.bind(this))
then(function () {
// If we don't have a user id we've never synced and don't need to bother
if (!Zotero.userID) {
return false;

View file

@ -32,6 +32,8 @@ Zotero.Styles = new function() {
var _initialized = false;
var _styles, _visibleStyles, _cacheTranslatorData;
var _renamedStyles = null;
Components.utils.import("resource://zotero/q.js");
Components.utils.import("resource://gre/modules/Services.jsm");
@ -116,22 +118,26 @@ Zotero.Styles = new function() {
/**
* Gets a style with a given ID
* @param {String} id
* @param {Boolean} skipMappings Don't automatically return renamed style
*/
this.get = function(id) {
// Map some obsolete styles to current ones
const MAPPINGS = {
"http://www.zotero.org/styles/chicago-note": "http://www.zotero.org/styles/chicago-note-bibliography",
"http://www.zotero.org/styles/mhra_note_without_bibliography": "http://www.zotero.org/styles/mhra",
"http://www.zotero.org/styles/aaa": "http://www.zotero.org/styles/american-anthropological-association",
"http://www.zotero.org/styles/ama": "http://www.zotero.org/styles/american-medical-association",
"http://www.zotero.org/styles/nlm": "http://www.zotero.org/styles/national-library-of-medicine"
};
this.get = function(id, skipMappings) {
if(!_initialized) this.init();
if(MAPPINGS.hasOwnProperty(id) && _styles[MAPPINGS[id]]) {
Zotero.debug("Mapping " + id + " to " + MAPPINGS[id]);
return _styles[MAPPINGS[id]];
// Map some obsolete styles to current ones
if(!_renamedStyles) {
_renamedStyles = JSON.parse(Zotero.File.getContentsFromURL(
"resource://zotero/schema/renamed-styles.json"
));
}
if(!skipMappings) {
var prefix = "http://www.zotero.org/styles/";
var shortName = id.replace(prefix, "");
if(_renamedStyles.hasOwnProperty(shortName) && _styles[prefix + _renamedStyles[shortName]]) {
let newID = prefix + _renamedStyles[shortName];
Zotero.debug("Mapping " + id + " to " + newID);
return _styles[newID];
}
}
return _styles[id] || false;

View file

@ -4019,7 +4019,9 @@ Zotero.Sync.Server.Data = new function() {
var msg = Zotero.getString('sync.error.invalidCharsFilename', filename);
var e = new Zotero.Error(msg, 0, { dialogButtonText: null });
throw (e);
}
if (item.attachment.linkMode == Zotero.Attachments.LINK_MODE_LINKED_FILE) {
path = Zotero.Attachments.getBaseDirectoryRelativePath(path);
}
var pathElem = doc.createElement('path');
pathElem.appendChild(doc.createTextNode(path));

View file

@ -2307,7 +2307,7 @@ Zotero.Translate.IO = {
throw "DOMParser error: loading data into data store failed";
}
nodes.normalize();
if("normalize" in nodes) nodes.normalize();
return nodes;
},

View file

@ -285,45 +285,93 @@ Zotero.Translate.ItemSaver.prototype = {
return newItem;
},
"_parsePath":function(path) {
// generate nsIFile
var IOService = Components.classes["@mozilla.org/network/io-service;1"].
getService(Components.interfaces.nsIIOService);
"_parsePathURI":function(path) {
try {
var uri = IOService.newURI(Zotero.File.encodeFilePath(path), "", this._baseURI);
var uri = Services.io.newURI(path, "", this._baseURI);
var file = uri.QueryInterface(Components.interfaces.nsIFileURL).file;
if(file.path != '/' && file.exists()) return file;
}
catch (e) {
var msg = "Error parsing attachment path: " + path + "\n" + e.message;
Zotero.logError(msg);
Zotero.debug("Translate: " + msg, 2);
return false;
Zotero.logError(e);
}
return false;
},
"_parseAbsolutePath":function(path) {
try {
var file = uri.QueryInterface(Components.interfaces.nsIFileURL).file;
if (file.path == '/') {
var msg = "Error parsing attachment path: " + path + "\nRoot path returned.";
Zotero.logError(msg);
Zotero.debug("Translate: " + msg, 2);
return false;
// First, try to parse absolute paths using initWithPath
var file = Components.classes["@mozilla.org/file/local;1"].
createInstance(Components.interfaces.nsILocalFile);
file.initWithPath(path);
if(file.exists()) return file;
} catch(e) {
Zotero.logError(e);
}
return false;
},
"_parseRelativePath":function(path) {
try {
var file = this._baseURI.QueryInterface(Components.interfaces.nsIFileURL).file.parent;
var splitPath = path.split(/\//g);
for(var i=0; i<splitPath.length; i++) {
if(splitPath[i] !== "") file.append(splitPath[i]);
}
if(file.exists()) return file;
} catch(e) {
Zotero.logError(e);
}
return false;
},
"_parsePath":function(path) {
var file;
// First, try to parse as absolute path
if(((/[a-zA-Z]:\\/.test(path) && Zotero.isWin) || (path[0] === "/" && !Zotero.isWin))
&& (file = this._parseAbsolutePath(path))) {
Zotero.debug("Translate: Got file "+path+" as absolute path");
return file;
}
// Next, try to parse as URI
if((file = this._parsePathURI(path))) {
Zotero.debug("Translate: Got "+path+" as URI")
return file;
} else if(path.substr(0, 7) !== "file://") {
// If it was a fully qualified file URI, we can give up now
// Next, try to parse as relative path, replacing backslashes with slashes
if((file = this._parseRelativePath(path.replace(/\\/g, "/")))) {
Zotero.debug("Translate: Got file "+path+" as relative path");
return file;
}
// Next, try to parse as relative path, without replacing backslashes with slashes
if((file = this._parseRelativePath(path))) {
Zotero.debug("Translate: Got file "+path+" as relative path");
return file;
}
if(path[0] !== "/") {
// Next, try to parse a path with no / as an absolute URI or path
if((file = this._parsePathURI("/"+path))) {
Zotero.debug("Translate: Got file "+path+" as broken URI");
return file;
}
if((file = this._parseAbsolutePath("/"+path))) {
Zotero.debug("Translate: Got file "+path+" as broken absolute path");
return file;
}
}
}
catch (e) {
var msg = "Error getting file from attachment path: " + path + "\n" + e.message;
Zotero.logError(msg);
Zotero.debug("Translate: " + msg, 2);
return false;
}
if(file.exists()) {
return file;
} else if(path[0] !== "/" && path.substr(0, 5).toLowerCase() !== "file:") {
// This looks like a relative path, but it might actually be an absolute path, because
// some people are not quite there.
var newFile = this._parsePath("/"+path);
if(newFile && newFile.exists()) return newFile;
}
// Give up
Zotero.debug("Translate: Could not find file "+path)
return false;
},

View file

@ -35,6 +35,8 @@ const ZOTERO_CONFIG = {
API_URL: 'https://api.zotero.org/',
API_VERSION: 2,
PREF_BRANCH: 'extensions.zotero.',
BOOKMARKLET_ORIGIN : 'https://www.zotero.org',
HTTP_BOOKMARKLET_ORIGIN : 'http://www.zotero.org',
BOOKMARKLET_URL: 'https://www.zotero.org/bookmarklet/',
VERSION: "4.1a1.SOURCE"
};

View file

@ -3087,7 +3087,8 @@ var ZoteroPane = new function()
if (itemType == 'temporaryPDFHack') {
itemType = null;
var isPDF = false;
if (doc.title.indexOf('application/pdf') != -1 || Zotero.Attachments.isPDFJS(doc)) {
if (doc.title.indexOf('application/pdf') != -1 || Zotero.Attachments.isPDFJS(doc)
|| doc.contentType == 'application/pdf') {
isPDF = true;
}
else {
@ -3444,8 +3445,9 @@ var ZoteroPane = new function()
}
var file = item.getFile();
Zotero.debug("Opening " + file.path);
if (file) {
Zotero.debug("Opening " + file.path);
if(forceExternalViewer !== undefined) {
var externalViewer = forceExternalViewer;
} else {

View file

@ -203,4 +203,5 @@
<!ENTITY zotero.preferences.openAboutConfig "Open about:config">
<!ENTITY zotero.preferences.openCSLEdit "Open CSL Editor">
<!ENTITY zotero.preferences.openCSLPreview "Open CSL Preview">
<!ENTITY zotero.preferences.openCSLPreview "Open CSL Preview">
<!ENTITY zotero.preferences.openAboutMemory "Open about:memory">

View file

@ -107,7 +107,6 @@
}
.quick-format-bubble {
-moz-border-radius: 8px;
border-radius: 8px;
background-color: #dee7f8;
border-style: solid;
@ -124,7 +123,6 @@
}
.quick-format-bubble[selected="true"] {
-moz-border-radius: 8px !important;
border-radius: 8px !important;
background-color: #598bec;
color: #fff;

View file

@ -179,7 +179,6 @@ label.zotero-text-link {
.zotero-clicky
{
-moz-border-radius: 6px;
border-radius: 6px;
border: 1px solid transparent;
}

View file

@ -44,7 +44,7 @@ function ZoteroAutoComplete() {
}
ZoteroAutoComplete.prototype.startSearch = function(searchString, searchParam, previousResult, listener) {
ZoteroAutoComplete.prototype.startSearch = function(searchString, searchParams, previousResult, listener) {
var result = Cc["@mozilla.org/autocomplete/simple-result;1"]
.createInstance(Ci.nsIAutoCompleteSimpleResult);
result.setSearchString(searchString);
@ -54,35 +54,35 @@ ZoteroAutoComplete.prototype.startSearch = function(searchString, searchParam, p
this._listener = listener;
this._cancelled = false;
this._zotero.debug("Starting autocomplete search of type '"
+ searchParam + "'" + " with string '" + searchString + "'");
this._zotero.debug("Starting autocomplete search with data '"
+ searchParams + "'" + " and string '" + searchString + "'");
searchParams = JSON.parse(searchParams);
if (!searchParams) {
throw new Error("Invalid JSON passed to autocomplete");
}
var [fieldName, , subField] = searchParams.fieldName.split("-");
this.stopSearch();
var self = this;
var statement;
// Allow extra parameters to be passed in
var pos = searchParam.indexOf('/');
if (pos!=-1){
var extra = searchParam.substr(pos + 1);
var searchParam = searchParam.substr(0, pos);
}
var searchParts = searchParam.split('-');
searchParam = searchParts[0];
switch (searchParam) {
switch (fieldName) {
case '':
break;
case 'tag':
var sql = "SELECT DISTINCT name AS val, NULL AS comment FROM tags WHERE name LIKE ?";
var sqlParams = [searchString + '%'];
if (extra){
if (typeof searchParams.libraryID != 'undefined') {
sql += " AND libraryID=?";
sqlParams.push(searchParams.libraryID);
}
if (searchParams.itemID) {
sql += " AND name NOT IN (SELECT name FROM tags WHERE tagID IN ("
+ "SELECT tagID FROM itemTags WHERE itemID = ?))";
sqlParams.push(extra);
sqlParams.push(searchParams.itemID);
}
statement = this._zotero.DB.getStatement(sql, sqlParams);
@ -103,22 +103,24 @@ ZoteroAutoComplete.prototype.startSearch = function(searchString, searchParam, p
// 0 == search two-field creators
// 1 == search single-field creators
// 2 == search both
var [fieldMode, itemID] = extra.split('-');
if (fieldMode==2)
{
if (searchParams.fieldMode == 2) {
var sql = "SELECT DISTINCT CASE fieldMode WHEN 1 THEN lastName "
+ "WHEN 0 THEN firstName || ' ' || lastName END AS val, NULL AS comment "
+ "FROM creators NATURAL JOIN creatorData WHERE CASE fieldMode "
+ "WHEN 1 THEN lastName "
+ "WHEN 0 THEN firstName || ' ' || lastName END "
+ "LIKE ? ORDER BY val";
var sqlParams = searchString + '%';
+ "LIKE ? ";
var sqlParams = [searchString + '%'];
if (typeof searchParams.libraryID != 'undefined') {
sql += " AND libraryID=?";
sqlParams.push(searchParams.libraryID);
}
sql += "ORDER BY val";
}
else
{
var sql = "SELECT DISTINCT ";
if (fieldMode==1){
if (searchParams.fieldMode == 1) {
sql += "lastName AS val, creatorID || '-1' AS comment";
}
// Retrieve the matches in the specified field
@ -138,22 +140,35 @@ ZoteroAutoComplete.prototype.startSearch = function(searchString, searchParam, p
}
var fromSQL = " FROM creators NATURAL JOIN creatorData "
+ "WHERE " + searchParts[2] + " LIKE ?1 " + "AND fieldMode=?2";
var sqlParams = [searchString + '%',
fieldMode ? parseInt(fieldMode) : 0];
if (itemID){
+ "WHERE " + subField + " LIKE ?1 " + "AND fieldMode=?2";
var sqlParams = [
searchString + '%',
searchParams.fieldMode ? searchParams.fieldMode : 0
];
if (searchParams.itemID) {
fromSQL += " AND creatorID NOT IN (SELECT creatorID FROM "
+ "itemCreators WHERE itemID=?3)";
sqlParams.push(itemID);
sqlParams.push(searchParams.itemID);
}
if (typeof searchParams.libraryID != 'undefined') {
if (searchParams.libraryID) {
fromSQL += " AND libraryID=?4";
sqlParams.push(searchParams.libraryID);
}
// The db query code doesn't properly replace numbered
// parameters with "IS NULL"
else {
fromSQL += " AND libraryID IS NULL";
}
}
sql += fromSQL;
// If double-field mode, include matches for just this field
// as well (i.e. "Shakespeare"), and group to collapse repeats
if (fieldMode!=1){
if (searchParams.fieldMode != 1) {
sql = "SELECT * FROM (" + sql + " UNION SELECT DISTINCT "
+ searchParts[2] + " AS val, creatorID || '-1' AS comment"
+ subField + " AS val, creatorID || '-1' AS comment"
+ fromSQL + ") GROUP BY val";
}
@ -165,8 +180,8 @@ ZoteroAutoComplete.prototype.startSearch = function(searchString, searchParam, p
case 'dateModified':
case 'dateAdded':
var sql = "SELECT DISTINCT DATE(" + searchParam + ", 'localtime') AS val, NULL AS comment FROM items "
+ "WHERE " + searchParam + " LIKE ? ORDER BY " + searchParam;
var sql = "SELECT DISTINCT DATE(" + fieldName + ", 'localtime') AS val, NULL AS comment FROM items "
+ "WHERE " + fieldName + " LIKE ? ORDER BY " + fieldName;
var sqlParams = [searchString + '%'];
statement = this._zotero.DB.getStatement(sql, sqlParams);
break;
@ -181,9 +196,9 @@ ZoteroAutoComplete.prototype.startSearch = function(searchString, searchParam, p
break;
default:
var fieldID = this._zotero.ItemFields.getID(searchParam);
var fieldID = this._zotero.ItemFields.getID(fieldName);
if (!fieldID) {
this._zotero.debug("'" + searchParam + "' is not a valid autocomplete scope", 1);
this._zotero.debug("'" + fieldName + "' is not a valid autocomplete scope", 1);
this.updateResults([], false, Ci.nsIAutoCompleteResult.RESULT_IGNORED);
return;
}
@ -191,7 +206,7 @@ ZoteroAutoComplete.prototype.startSearch = function(searchString, searchParam, p
// We don't use date autocomplete anywhere, but if we're not
// disallowing it altogether, we should at least do it right and
// use the user part of the multipart field
var valueField = searchParam=='date' ? 'SUBSTR(value, 12, 100)' : 'value';
var valueField = fieldName == 'date' ? 'SUBSTR(value, 12, 100)' : 'value';
var sql = "SELECT DISTINCT " + valueField + " AS val, NULL AS comment "
+ "FROM itemData NATURAL JOIN itemDataValues "
@ -199,10 +214,10 @@ ZoteroAutoComplete.prototype.startSearch = function(searchString, searchParam, p
+ " LIKE ?2 "
var sqlParams = [fieldID, searchString + '%'];
if (extra){
if (searchParams.itemID) {
sql += "AND value NOT IN (SELECT value FROM itemData "
+ "NATURAL JOIN itemDataValues WHERE fieldID=?1 AND itemID=?3) ";
sqlParams.push(extra);
sqlParams.push(searchParams.itemID);
}
sql += "ORDER BY value";
statement = this._zotero.DB.getStatement(sql, sqlParams);

View file

@ -0,0 +1,162 @@
{
"aaa": "american-anthropological-association",
"advances-physiology-education": "advances-in-physiology-education",
"agriculture-ecosystems-environment": "agriculture-ecosystems-and-environment",
"ajp-heart-circulatory-physiology": "ajp-heart-and-circulatory-physiology",
"ajp-regulatory-integrative-comparative-physiology": "ajp-regulatory-integrative-and-comparative-physiology",
"ama": "american-medical-association",
"american-journal-of-cardiology": "the-american-journal-of-cardiology",
"american-journal-of-clinical-nutrition": "the-american-journal-of-clinical-nutrition",
"american-journal-of-emergency-medicine": "the-american-journal-of-emergency-medicine",
"american-journal-of-medicine": "the-american-journal-of-medicine",
"american-journal-of-pathology": "the-american-journal-of-pathology",
"american-journal-of-sports-medicine": "the-american-journal-of-sports-medicine",
"american-journal-of-surgery": "the-american-journal-of-surgery",
"american-journal-of-tropical-medicine-and-hygiene": "the-american-journal-of-tropical-medicine-and-hygiene",
"american-medical-writers-association": "american-medical-writers-association-journal",
"american-surgeon": " the-american-surgeon",
"amiens": "universite-de-picardie-jules-verne-ufr-de-medecine",
"annalen-des-naturhistorischen-museums-wien": "annalen-des-naturhistorischen-museums-in-wien",
"annals-of-allergy": "annals-of-allergy-asthma-and-immunology",
"annals-of-thoracic-surgery": "the-annals-of-thoracic-surgery",
"annual-reviews-alphabetically": "annual-reviews-alphabetical",
"annual-reviews-by-appearance": "annual-reviews",
"apa5th": "apa-5th-edition",
"apsa": "american-political-science-association",
"asa": "american-sociological-association",
"bba-biochimica-et-biophysica-acta": "biochimica-et-biophysica-acta",
"bio-medical-reviews": "biomedical-reviews",
"bmc-pharmacology": "bmc-pharmacology-and-toxicology",
"bmj-supportive-palliative-care": "bmj-supportive-and-palliative-care",
"brain-and-development-english-language": "brain-and-development",
"british-journal-of-medical-economics": "journal-of-medical-economics",
"british-volume-of-the-journal-of-bone-and-joint-surgery": "the-journal-of-bone-and-joint-surgery",
"bulletin-of-the-medical-library-association": "journal-of-the-medical-library-association",
"canadian-journal-of-anaesthesia": "canadian-journal-of-anesthesia",
"canadian-journal-of-hospital-pharmacy": "the-canadian-journal-of-hospital-pharmacy",
"canadian-medical-association-journal": "cmaj",
"canadian-veterinary-journal": "the-canadian-veterinary-journal",
"cancer-epidemiology-biomarkers-prevention": "cancer-epidemiology-biomarkers-and-prevention",
"cardiovascular-pharmacology-and-therapeutics": "journal-of-cardiovascular-pharmacology-and-therapeutics",
"central-african-journal-of-medicine": "the-central-african-journal-of-medicine",
"ceylon-journal-of-medical-science": "the-ceylon-journal-of-medical-science",
"ceylon-medical-journal": "the-ceylon-medical-journal",
"chicago-note": "chicago-note-bibliography",
"chronic-diseases-in-canada": "chronic-diseases-and-injuries-in-canada",
"college-of-physicians-and-surgeons-pakistan": "journal-of-the-college-of-physicians-and-surgeons-pakistan",
"cuadernos-filologia-clasica": "cuadernos-de-filologia-clasica",
"current-opinion-biotechnology": "current-opinion-in-biotechnology",
"current-opinion-cell-biology": "current-opinion-in-cell-biology",
"current-opinion-chemical-biology": "current-opinion-in-chemical-biology",
"current-opinion-environmental-sustainability": "current-opinion-in-environmental-sustainability",
"current-opinion-genetics-development": "current-opinion-in-genetics-development",
"current-opinion-immunology": "current-opinion-in-immunology",
"current-opinion-microbiology": "current-opinion-in-microbiology",
"current-opinion-neurobiology": "current-opinion-in-neurobiology",
"current-opinion-pharmacology": "current-opinion-in-pharmacology",
"current-opinion-plant-biology": "current-opinion-in-plant-biology",
"current-opinion-structural-biology": "current-opinion-in-structural-biology",
"danish-dental-journal": "tandlaegebladet",
"diabetes-vascular-disease-research": "diabetes-and-vascular-disease-research",
"disease-models-mechanisms": "disease-models-and-mechanisms",
"diseases-aquatic-organisms": "diseases-of-aquatic-organisms",
"edizioni-minerva-medica": "minerva-medica",
"ethics-science-environmental-politics": "ethics-in-science-and-environmental-politics",
"f1000-research": "f1000research",
"febs-journal": "the-febs-journal",
"fems": "federation-of-european-microbiological-societies",
"firstmonday": "first-monday",
"future-science": "future-science-journals",
"geological-society-america-bulletin": "geological-society-of-america-bulletin",
"geological-society-of-america": "the-geological-society-of-america",
"gost-r-7-0-5-2008-csl-1-0": "gost-r-7-0-5-2008",
"graefes-archive-and-experimental-ophthalmology": "graefes-archive-for-clinical-and-experimental-ophthalmology",
"harvard-anglia-ruskin": "harvard-anglia-ruskin-university",
"harvard-sheffield": "harvard-the-university-of-sheffield-town-and-regional-planning",
"harvard-sheffield1": "harvard-the-university-of-sheffield-school-of-east-asian-studies",
"harvard-university-of-northampton": "harvard-the-university-of-northampton",
"harvard-university-west-london": "harvard-university-of-west-london",
"harvard1-unisa-gbfe": "harvard-gesellschaft-fur-bildung-und-forschung-in-europa",
"harvard3": "harvard-swinburne-university-of-technology",
"hbp": "hpb",
"hwr-berlin": "hochschule-fur-wirtschaft-und-recht-berlin",
"ices-jms": "ices-journal-of-marine-science",
"ieee-w-url": "ieee-with-url",
"institute-of-electronics-information-and-communication-engineers": "the-institute-of-electronics-information-and-communication-engineers",
"international-journal-cross-cultural-management": "international-journal-of-cross-cultural-management",
"international-journal-of-psychiatry-in-medicine": "the-international-journal-of-psychiatry-in-medicine",
"international-journal-of-psychoanalysis": "the-international-journal-of-psychoanalysis",
"international-journal-of-tropical-biology-and-conservation": "revista-de-biologia-tropical",
"iso690-author-date-fr-without-abstract": "iso690-author-date-fr-no-abstract",
"jid-symposium-proceedings": "journal-of-investigative-dermatology-symposium-proceedings",
"journal-of-aapos": "journal-of-american-association-for-pediatric-ophthalmology-and-strabismus",
"journal-of-allergy-and-clinical-immunology": "the-journal-of-allergy-and-clinical-immunology",
"journal-of-bone-and-joint-surgery": "the-journal-of-bone-and-joint-surgery",
"journal-of-cardiovascular-surgery": "the-journal-of-cardiovascular-surgery",
"journal-of-cell-biology": "the-journal-of-cell-biology",
"journal-of-chemical-physics": "the-journal-of-chemical-physics",
"journal-of-clinical-endocrinology-and-metabolism": "the-journal-of-clinical-endocrinology-and-metabolism",
"journal-of-clinical-investigation": "the-journal-of-clinical-investigation",
"journal-of-clinical-psychiatry": "the-journal-of-clinical-psychiatry",
"journal-of-experimental-medicine": "the-journal-of-experimental-medicine",
"journal-of-general-physiology": "the-journal-of-general-physiology",
"journal-of-hand-surgery": "the-journal-of-hand-surgery",
"journal-of-heart-and-lung-transplantation": "the-journal-of-heart-and-lung-transplantation",
"journal-of-hellenic-studies": "the-journal-of-hellenic-studies",
"journal-of-hong-kong-medical-association": "hong-kong-medical-journal",
"journal-of-indian-prosthodontic-society": "the-journal-of-indian-prosthodontic-society",
"journal-of-juristic-papyrology": "the-journal-of-juristic-papyrology",
"journal-of-medieval-and-early-modern-studies": "the-journal-of-medieval-and-early-modern-studies",
"journal-of-modern-history": "the-journal-of-modern-history",
"journal-of-nuclear-medicine": "the-journal-of-nuclear-medicine",
"journal-of-organic-chemistry": "the-journal-of-organic-chemistry",
"journal-of-pediatrics": "the-journal-of-pediatrics",
"journal-of-pharmacology-and-experimental-therapeutics": "the-journal-of-pharmacology-and-experimental-therapeutics",
"journal-of-pharmacy-technology": "the-journal-of-pharmacy-technology",
"journal-of-physical-chemistry": "the-journal-of-physical-chemistry-a",
"journal-of-prosthetic-dentistry": "the-journal-of-prosthetic-dentistry",
"journal-of-the-american-academy-of-physician-assistants": "jaapa",
"journal-of-the-american-dental-association": "the-journal-of-the-american-dental-association",
"journal-of-the-american-medical-association": "jama",
"journal-of-the-american-osteopathic-association": "the-journal-of-the-american-osteopathic-association",
"journal-of-the-indian-society-of-pedodontics-and-preventative-dentistry": "journal-of-the-indian-society-of-pedodontics-and-preventive-dentistry",
"journal-of-the-institute-of-medicine": "journal-of-institute-of-medicine",
"journal-of-the-torrey-botanical-society": "the-journal-of-the-torrey-botanical-society",
"journal-of-thoracic-and-cardiovascular-surgery": "the-journal-of-thoracic-and-cardiovascular-surgery",
"journal-of-wildlife-management": "the-journal-of-wildlife-management",
"juristische-zitierweise-deutsch": "juristische-zitierweise",
"korean-journal-of-gynecologic-oncology": "journal-of-gynecologic-oncology",
"lancet-infectious-diseases": "the-lancet-infectious-diseases",
"lancet-neurology": "the-lancet-neurology",
"lancet-oncology": "the-lancet-oncology",
"lancet": "the-lancet",
"lichenologist": "the-lichenologist",
"lncs": "springer-lecture-notes-in-computer-science",
"lncs2": "springer-lecture-notes-in-computer-science-alphabetical",
"malaysian-journal-of-pathology": "the-malaysian-journal-of-pathology",
"manedsskrift-for-praktk-laegegerning": "manedsskrift-for-almen-praksis",
"medical-journal-of-australia": "the-medical-journal-of-australia",
"medicina-militar": "sanidad-militar",
"methods-information-medicine": "methods-of-information-in-medicine",
"mhra_note_without_bibliography": "modern-humanities-research-association",
"mhra-author-date": "modern-humanities-research-association-author-date",
"mhra": "modern-humanities-research-association",
"mla-notes": "modern-language-association-note",
"mla-underline": "modern-language-association-underline",
"mla-url": "modern-language-association-with-url",
"mla": "modern-language-association",
"molecular-biochemical-parasitology": "molecular-and-biochemical-parasitology",
"netherlands-journal-of-medicine": "the-netherlands-journal-of-medicine",
"neumologica-y-cirugia-de-torax-neurofibromatosis": "neumologia-y-cirugia-de-torax",
"new-iraqi-journal-of-medicine": "the-new-iraqi-journal-of-medicine",
"new-zealand-journal-of-medical-laboratory-technology": "new-zealand-journal-of-medical-laboratory-science",
"new-zealand-medical-journal": "the-new-zealand-medical-journal",
"nlm": "national-library-of-medicine",
"physiological-biochemical-zoology": "physiological-and-biochemical-zoology",
"quaderni-avogadro-colloquia": "quaderni-degli-avogadro-colloquia",
"taylor-and-francis-reference-style-f": "taylor-and-francis-chicago-f",
"ulster-medical-journal": "the-ulster-medical-journal",
"uni-freiburg-geschichte-autor-jahr": "universitat-freiburg-geschichte",
"uqam-universite-du-quebec-a-montreal": "universite-du-quebec-a-montreal",
"world-health-organization-journals": "world-health-organization"
}

View file

@ -1 +1 @@
2013-04-07 18:45:00
2013-04-15 18:15:00

2
styles

@ -1 +1 @@
Subproject commit b53019e1e601c6e843c58ad12c8149afc29ce4d6
Subproject commit e136c9f0b4cd82fcd1bed4b4a35bb7139a40d9ea

@ -1 +1 @@
Subproject commit c70b413c796b294f98a19667d48081ba4d042e0c
Subproject commit 95d2177e3e3500b7c05e3a4c6608e0b55a1c5ad3