diff --git a/chrome/content/zotero/overlay.js b/chrome/content/zotero/overlay.js
index f39c46b8c..f8c51296c 100644
--- a/chrome/content/zotero/overlay.js
+++ b/chrome/content/zotero/overlay.js
@@ -628,16 +628,16 @@ var ZoteroPane = new function()
return false;
}
- if (!this.canEdit(row)) {
- this.displayCannotEditLibraryMessage();
- return;
- }
-
// Currently selected row
if (row === undefined) {
row = this.collectionsView.selection.currentIndex;
}
+ if (!this.canEdit(row)) {
+ this.displayCannotEditLibraryMessage();
+ return;
+ }
+
if (row !== undefined) {
var itemGroup = this.collectionsView._getItemAtRow(row);
var libraryID = itemGroup.ref.libraryID;
@@ -2255,30 +2255,6 @@ var ZoteroPane = new function()
* regardless of automaticSnapshots pref
*/
this.addItemFromDocument = function (doc, itemType, saveSnapshot, row) {
- if (!Zotero.stateCheck()) {
- this.displayErrorMessage(true);
- return false;
- }
-
- // Currently selected row
- if (row === undefined) {
- row = this.collectionsView.selection.currentIndex;
- }
-
- if (!this.canEdit(row)) {
- this.displayCannotEditLibraryMessage();
- return;
- }
-
- if (row !== undefined) {
- var itemGroup = this.collectionsView._getItemAtRow(row);
- var libraryID = itemGroup.ref.libraryID;
- }
- else {
- var libraryID = null;
- var itemGroup = null;
- }
-
var progressWin = new Zotero.ProgressWindow();
progressWin.changeHeadline(Zotero.getString('ingester.scraping'));
var icon = 'chrome://zotero/skin/treeitem-webpage.png';
@@ -2286,12 +2262,6 @@ var ZoteroPane = new function()
progressWin.show();
progressWin.startCloseTimer();
- var data = {
- title: doc.title,
- url: doc.location.href,
- accessDate: "CURRENT_TIMESTAMP"
- }
-
// TODO: this, needless to say, is a temporary hack
if (itemType == 'temporaryPDFHack') {
itemType = null;
@@ -2315,6 +2285,36 @@ var ZoteroPane = new function()
}
if (isPDF) {
+ //
+ // Duplicate newItem() checks here
+ //
+ if (!Zotero.stateCheck()) {
+ this.displayErrorMessage(true);
+ return false;
+ }
+
+ // Currently selected row
+ if (row === undefined) {
+ row = this.collectionsView.selection.currentIndex;
+ }
+
+ if (!this.canEdit(row)) {
+ this.displayCannotEditLibraryMessage();
+ return;
+ }
+
+ if (row !== undefined) {
+ var itemGroup = this.collectionsView._getItemAtRow(row);
+ var libraryID = itemGroup.ref.libraryID;
+ }
+ else {
+ var libraryID = null;
+ var itemGroup = null;
+ }
+ //
+ //
+ //
+
if (libraryID) {
var pr = Components.classes["@mozilla.org/network/default-prompt;1"]
.getService(Components.interfaces.nsIPrompt);
@@ -2328,6 +2328,7 @@ var ZoteroPane = new function()
else {
var collectionID = false;
}
+
Zotero.Attachments.importFromDocument(doc, false, false, collectionID);
return;
}
@@ -2337,6 +2338,11 @@ var ZoteroPane = new function()
if (!itemType) {
itemType = 'webpage';
}
+ var data = {
+ title: doc.title,
+ url: doc.location.href,
+ accessDate: "CURRENT_TIMESTAMP"
+ }
itemType = Zotero.ItemTypes.getID(itemType);
var item = this.newItem(itemType, data, row);
@@ -2369,17 +2375,113 @@ var ZoteroPane = new function()
return this.addItemFromPage(itemType, saveSnapshot, row);
}
- var processor = function (doc) {
- ZoteroPane.addItemFromDocument(doc, itemType, saveSnapshot, row);
- };
-
- var done = function () {}
-
- var exception = function (e) {
- Zotero.debug(e);
- }
-
- Zotero.Utilities.HTTP.processDocuments([url], processor, done, exception);
+ Zotero.MIME.getMIMETypeFromURL(url, function (mimeType, hasNativeHandler) {
+ // If native type, save using a hidden browser
+ if (hasNativeHandler) {
+ var processor = function (doc) {
+ ZoteroPane.addItemFromDocument(doc, itemType, saveSnapshot, row);
+ };
+
+ var done = function () {}
+
+ var exception = function (e) {
+ Zotero.debug(e);
+ }
+
+ Zotero.Utilities.HTTP.processDocuments([url], processor, done, exception);
+ }
+ // Otherwise create placeholder item, attach attachment, and update from that
+ else {
+ // TODO: this, needless to say, is a temporary hack
+ if (itemType == 'temporaryPDFHack') {
+ itemType = null;
+
+ if (mimeType == 'application/pdf') {
+ //
+ // Duplicate newItem() checks here
+ //
+ if (!Zotero.stateCheck()) {
+ ZoteroPane.displayErrorMessage(true);
+ return false;
+ }
+
+ // Currently selected row
+ if (row === undefined) {
+ row = ZoteroPane.collectionsView.selection.currentIndex;
+ }
+
+ if (!ZoteroPane.canEdit(row)) {
+ ZoteroPane.displayCannotEditLibraryMessage();
+ return;
+ }
+
+ if (row !== undefined) {
+ var itemGroup = ZoteroPane.collectionsView._getItemAtRow(row);
+ var libraryID = itemGroup.ref.libraryID;
+ }
+ else {
+ var libraryID = null;
+ var itemGroup = null;
+ }
+ //
+ //
+ //
+
+ if (libraryID) {
+ var pr = Components.classes["@mozilla.org/network/default-prompt;1"]
+ .getService(Components.interfaces.nsIPrompt);
+ pr.alert("", "Files cannot currently be added to group libraries.");
+ return;
+ }
+
+ if (itemGroup && itemGroup.isCollection()) {
+ var collectionID = itemGroup.ref.id;
+ }
+ else {
+ var collectionID = false;
+ }
+
+ Zotero.Attachments.importFromURL(url, false, false, collectionID);
+ return;
+ }
+ }
+
+ if (!itemType) {
+ itemType = 'webpage';
+ }
+
+ var item = ZoteroPane.newItem(itemType, {}, row);
+
+ if (item.libraryID) {
+ var group = Zotero.Groups.getByLibraryID(item.libraryID);
+ filesEditable = group.filesEditable;
+ }
+ else {
+ filesEditable = true;
+ }
+
+ // Save snapshot if explicitly enabled or automatically pref is set and not explicitly disabled
+ if (saveSnapshot || (saveSnapshot !== false && Zotero.Prefs.get('automaticSnapshots'))) {
+ var link = false;
+
+ if (link) {
+ //Zotero.Attachments.linkFromURL(doc, item.id);
+ }
+ else if (filesEditable) {
+ var attachmentItem = Zotero.Attachments.importFromURL(url, item.id, false, false, false, mimeType);
+ if (attachmentItem) {
+ item.setField('title', attachmentItem.getField('title'));
+ item.setField('url', attachmentItem.getField('url'));
+ item.setField('accessDate', attachmentItem.getField('accessDate'));
+ item.save();
+ }
+ }
+ }
+
+ return item.id;
+
+ }
+ });
}
diff --git a/chrome/content/zotero/overlay.xul b/chrome/content/zotero/overlay.xul
index 89f11bf92..ca157a29f 100644
--- a/chrome/content/zotero/overlay.xul
+++ b/chrome/content/zotero/overlay.xul
@@ -63,7 +63,7 @@
+ oncommand="ZoteroPane.addItemFromURL(window.gContextMenu.linkURL, 'temporaryPDFHack')"/>
diff --git a/chrome/content/zotero/xpcom/attachments.js b/chrome/content/zotero/xpcom/attachments.js
index f7fc04347..848669c7b 100644
--- a/chrome/content/zotero/xpcom/attachments.js
+++ b/chrome/content/zotero/xpcom/attachments.js
@@ -187,7 +187,7 @@ Zotero.Attachments = new function(){
}
- function importFromURL(url, sourceItemID, forceTitle, forceFileBaseName, parentCollectionIDs){
+ function importFromURL(url, sourceItemID, forceTitle, forceFileBaseName, parentCollectionIDs, mimeType) {
Zotero.debug('Importing attachment from URL');
if (sourceItemID && parentCollectionIDs) {
@@ -206,180 +206,181 @@ Zotero.Attachments = new function(){
throw ("Invalid URL '" + url + "' in Zotero.Attachments.importFromURL()");
}
- Zotero.Utilities.HTTP.doHead(url, function(obj){
- if (obj.status != 200 && obj.status != 204) {
- Zotero.debug("Attachment HEAD request returned with status code "
- + obj.status + " in Attachments.importFromURL()", 2);
- var mimeType = '';
- }
- else {
- var mimeType = obj.channel.contentType;
- }
-
- var nsIURL = Components.classes["@mozilla.org/network/standard-url;1"]
- .createInstance(Components.interfaces.nsIURL);
- nsIURL.spec = url;
-
- // Override MIME type to application/pdf if extension is .pdf --
- // workaround for sites that respond to the HEAD request with an
- // invalid MIME type (https://www.zotero.org/trac/ticket/460)
- //
- // Downloaded file is inspected below and deleted if actually HTML
- if (nsIURL.fileName.match(/pdf$/) || url.match(/pdf$/)) {
- mimeType = 'application/pdf';
- }
-
- // If we can load this natively, use a hidden browser (so we can
- // get the charset and title and index the document)
- if (Zotero.MIME.hasNativeHandler(mimeType, ext)){
- var browser = Zotero.Browser.createHiddenBrowser();
- var imported = false;
- var onpageshow = function() {
- // ignore spurious about:blank loads
- if(browser.contentDocument.location.href == "about:blank") return;
-
- // pageshow can be triggered multiple times on some pages,
- // so make sure we only import once
- // (https://www.zotero.org/trac/ticket/795)
- if (imported) {
- return;
- }
- var callback = function () {
- browser.removeEventListener("pageshow", onpageshow, false);
- Zotero.Browser.deleteHiddenBrowser(browser);
- };
- Zotero.Attachments.importFromDocument(browser.contentDocument,
- sourceItemID, forceTitle, parentCollectionIDs, callback);
- imported = true;
+ // Save using a hidden browser
+ var nativeHandlerImport = function () {
+ var browser = Zotero.Browser.createHiddenBrowser();
+ var imported = false;
+ var onpageshow = function() {
+ // ignore spurious about:blank loads
+ if(browser.contentDocument.location.href == "about:blank") return;
+
+ // pageshow can be triggered multiple times on some pages,
+ // so make sure we only import once
+ // (https://www.zotero.org/trac/ticket/795)
+ if (imported) {
+ return;
+ }
+ var callback = function () {
+ browser.removeEventListener("pageshow", onpageshow, false);
+ Zotero.Browser.deleteHiddenBrowser(browser);
};
- browser.addEventListener("pageshow", onpageshow, false);
- browser.loadURI(url);
+ Zotero.Attachments.importFromDocument(browser.contentDocument,
+ sourceItemID, forceTitle, parentCollectionIDs, callback);
+ imported = true;
+ };
+ browser.addEventListener("pageshow", onpageshow, false);
+ browser.loadURI(url);
+ };
+
+ // Save using remote web browser persist
+ var externalHandlerImport = function (mimeType) {
+ if (forceFileBaseName) {
+ var ext = _getExtensionFromURL(url, mimeType);
+ var fileName = forceFileBaseName + (ext != '' ? '.' + ext : '');
+ }
+ else {
+ var fileName = _getFileNameFromURL(url, mimeType);
}
- // Otherwise use a remote web page persist
- else {
- if (forceFileBaseName) {
- var ext = _getExtensionFromURL(url, mimeType);
- var fileName = forceFileBaseName + (ext != '' ? '.' + ext : '');
+ var title = forceTitle ? forceTitle : fileName;
+
+ const nsIWBP = Components.interfaces.nsIWebBrowserPersist;
+ var wbp = Components
+ .classes["@mozilla.org/embedding/browser/nsWebBrowserPersist;1"]
+ .createInstance(nsIWBP);
+ wbp.persistFlags = nsIWBP.PERSIST_FLAGS_AUTODETECT_APPLY_CONVERSION;
+ var encodingFlags = false;
+
+ Zotero.DB.beginTransaction();
+
+ try {
+ // Create a new attachment
+ var attachmentItem = new Zotero.Item('attachment');
+ if (sourceItemID) {
+ var parentItem = Zotero.Items.get(sourceItemID);
+ attachmentItem.libraryID = parentItem.libraryID;
}
- else {
- var fileName = _getFileNameFromURL(url, mimeType);
+ attachmentItem.setField('title', title);
+ attachmentItem.setField('url', url);
+ attachmentItem.setField('accessDate', "CURRENT_TIMESTAMP");
+ attachmentItem.setSource(sourceItemID);
+ attachmentItem.attachmentLinkMode = Zotero.Attachments.LINK_MODE_IMPORTED_URL;
+ attachmentItem.attachmentMIMEType = mimeType;
+ var itemID = attachmentItem.save();
+ attachmentItem = Zotero.Items.get(itemID);
+
+ // Add to collections
+ if (parentCollectionIDs){
+ var ids = Zotero.flattenArguments(parentCollectionIDs);
+ for each(var id in ids){
+ var col = Zotero.Collections.get(id);
+ col.addItem(itemID);
+ }
}
- var title = forceTitle ? forceTitle : fileName;
+ // Create a new folder for this item in the storage directory
+ var destDir = Zotero.Attachments.createDirectoryForItem(itemID);
- const nsIWBP = Components.interfaces.nsIWebBrowserPersist;
- var wbp = Components
- .classes["@mozilla.org/embedding/browser/nsWebBrowserPersist;1"]
- .createInstance(nsIWBP);
- wbp.persistFlags = nsIWBP.PERSIST_FLAGS_AUTODETECT_APPLY_CONVERSION;
- var encodingFlags = false;
+ var file = destDir.clone();
+ file.append(fileName);
- Zotero.DB.beginTransaction();
+ wbp.progressListener = new Zotero.WebProgressFinishListener(function(){
+ try {
+ var str = Zotero.File.getSample(file);
+
+ if (mimeType == 'application/pdf' &&
+ Zotero.MIME.sniffForMIMEType(str) != 'application/pdf') {
+ Zotero.debug("Downloaded PDF did not have MIME type "
+ + "'application/pdf' in Attachments.importFromURL()", 2);
+ attachmentItem.erase();
+ return;
+ }
+
+ attachmentItem.attachmentPath =
+ Zotero.Attachments.getPath(
+ file, Zotero.Attachments.LINK_MODE_IMPORTED_URL
+ );
+ attachmentItem.save();
+
+ Zotero.Notifier.trigger('add', 'item', itemID);
+ Zotero.Notifier.trigger('modify', 'item', sourceItemID);
+
+ // We don't have any way of knowing that the file
+ // is flushed to disk, so we just wait a second
+ // and hope for the best -- we'll index it later
+ // if it fails
+ //
+ // TODO: index later
+ var timer = Components.classes["@mozilla.org/timer;1"].
+ createInstance(Components.interfaces.nsITimer);
+ timer.initWithCallback({notify: function() {
+ Zotero.Fulltext.indexItems([itemID]);
+ }}, 1000, Components.interfaces.nsITimer.TYPE_ONE_SHOT);
+ }
+ catch (e) {
+ // Clean up
+ attachmentItem.erase();
+
+ throw (e);
+ }
+ });
+
+ // Disable the Notifier during the commit
+ var disabled = Zotero.Notifier.disable();
+
+ // The attachment is still incomplete here, but we can't risk
+ // leaving the transaction open if the callback never triggers
+ Zotero.DB.commitTransaction();
+
+ if (disabled) {
+ Zotero.Notifier.enable();
+ }
+
+ var nsIURL = Components.classes["@mozilla.org/network/standard-url;1"]
+ .createInstance(Components.interfaces.nsIURL);
+ nsIURL.spec = url;
+ wbp.saveURI(nsIURL, null, null, null, null, file);
+
+ return attachmentItem;
+ }
+ catch (e){
+ Zotero.DB.rollbackTransaction();
try {
- // Create a new attachment
- var attachmentItem = new Zotero.Item('attachment');
- if (sourceItemID) {
- var parentItem = Zotero.Items.get(sourceItemID);
- attachmentItem.libraryID = parentItem.libraryID;
- }
- attachmentItem.setField('title', title);
- attachmentItem.setField('url', url);
- attachmentItem.setField('accessDate', "CURRENT_TIMESTAMP");
- attachmentItem.setSource(sourceItemID);
- attachmentItem.attachmentLinkMode = Zotero.Attachments.LINK_MODE_IMPORTED_URL;
- attachmentItem.attachmentMIMEType = mimeType;
- var itemID = attachmentItem.save();
- attachmentItem = Zotero.Items.get(itemID);
-
- // Add to collections
- if (parentCollectionIDs){
- var ids = Zotero.flattenArguments(parentCollectionIDs);
- for each(var id in ids){
- var col = Zotero.Collections.get(id);
- col.addItem(itemID);
+ // Clean up
+ if (itemID) {
+ var itemDir = this.getStorageDirectory(itemID);
+ if (itemDir.exists()) {
+ itemDir.remove(true);
}
}
-
- // Create a new folder for this item in the storage directory
- var destDir = Zotero.Attachments.createDirectoryForItem(itemID);
-
- var file = destDir.clone();
- file.append(fileName);
-
- wbp.progressListener = new Zotero.WebProgressFinishListener(function(){
- try {
- var str = Zotero.File.getSample(file);
-
- if (mimeType == 'application/pdf' &&
- Zotero.MIME.sniffForMIMEType(str) != 'application/pdf') {
- Zotero.debug("Downloaded PDF did not have MIME type "
- + "'application/pdf' in Attachments.importFromURL()", 2);
- attachmentItem.erase();
- return;
- }
-
- attachmentItem.attachmentPath =
- Zotero.Attachments.getPath(
- file, Zotero.Attachments.LINK_MODE_IMPORTED_URL
- );
- attachmentItem.save();
-
- Zotero.Notifier.trigger('add', 'item', itemID);
- Zotero.Notifier.trigger('modify', 'item', sourceItemID);
-
- // We don't have any way of knowing that the file
- // is flushed to disk, so we just wait a second
- // and hope for the best -- we'll index it later
- // if it fails
- //
- // TODO: index later
- var timer = Components.classes["@mozilla.org/timer;1"].
- createInstance(Components.interfaces.nsITimer);
- timer.initWithCallback({notify: function() {
- Zotero.Fulltext.indexItems([itemID]);
- }}, 1000, Components.interfaces.nsITimer.TYPE_ONE_SHOT);
- }
- catch (e) {
- // Clean up
- attachmentItem.erase();
-
- throw (e);
- }
- });
-
- // Disable the Notifier during the commit
- var disabled = Zotero.Notifier.disable();
-
- // The attachment is still incomplete here, but we can't risk
- // leaving the transaction open if the callback never triggers
- Zotero.DB.commitTransaction();
-
- if (disabled) {
- Zotero.Notifier.enable();
- }
-
- wbp.saveURI(nsIURL, null, null, null, null, file);
- }
- catch (e){
- Zotero.DB.rollbackTransaction();
-
- try {
- // Clean up
- if (itemID) {
- var itemDir = this.getStorageDirectory(itemID);
- if (itemDir.exists()) {
- itemDir.remove(true);
- }
- }
- }
- catch (e) {}
-
- throw (e);
}
+ catch (e) {}
+
+ throw (e);
}
- });
+ }
+
+ var process = function (mimeType, hasNativeHandler) {
+ // If we can load this natively, use a hidden browser
+ // (so we can get the charset and title and index the document)
+ if (hasNativeHandler) {
+ nativeHandlerImport();
+ }
+ // Otherwise use a remote web page persist
+ else {
+ return externalHandlerImport(mimeType);
+ }
+ }
+
+ if (mimeType) {
+ return process(mimeType);
+ }
+ else {
+ Zotero.MIME.getMIMETypeFromURL(url, function (mimeType, hasNativeHandler) {
+ process(mimeType, hasNativeHandler);
+ });
+ }
}
@@ -425,9 +426,7 @@ Zotero.Attachments = new function(){
if (!mimeType) {
// If we don't have the MIME type, do a HEAD request for it
- Zotero.Utilities.HTTP.doHead(url, function(obj){
- var mimeType = obj.channel.contentType;
-
+ Zotero.MIME.getMIMETypeFromURL(url, function (mimeType) {
if (mimeType) {
var disabled = Zotero.Notifier.disable();
diff --git a/chrome/content/zotero/xpcom/mime.js b/chrome/content/zotero/xpcom/mime.js
index 8a53d2687..5440863eb 100644
--- a/chrome/content/zotero/xpcom/mime.js
+++ b/chrome/content/zotero/xpcom/mime.js
@@ -275,6 +275,38 @@ Zotero.MIME = new function(){
}
+ this.getMIMETypeFromURL = function (url, callback) {
+ Zotero.Utilities.HTTP.doHead(url, function(xmlhttp) {
+ if (xmlhttp.status != 200 && xmlhttp.status != 204) {
+ Zotero.debug("Attachment HEAD request returned with status code "
+ + xmlhttp.status + " in Zotero.MIME.getMIMETypeFromURL()", 2);
+ var mimeType = '';
+ }
+ else {
+ var mimeType = xmlhttp.channel.contentType;
+ }
+
+ var nsIURL = Components.classes["@mozilla.org/network/standard-url;1"]
+ .createInstance(Components.interfaces.nsIURL);
+ nsIURL.spec = url;
+
+ // Override MIME type to application/pdf if extension is .pdf --
+ // workaround for sites that respond to the HEAD request with an
+ // invalid MIME type (https://www.zotero.org/trac/ticket/460)
+ //
+ // Downloaded file is inspected in attachment code and deleted if actually HTML
+ if (nsIURL.fileName.match(/pdf$/) || url.match(/pdf$/)) {
+ mimeType = 'application/pdf';
+ }
+
+ var ext = nsIURL.fileExtension;
+ var hasNativeHandler = Zotero.MIME.hasNativeHandler(mimeType, ext)
+
+ callback(mimeType, hasNativeHandler);
+ });
+ }
+
+
/*
* Determine if a MIME type can be handled natively
* or if it needs to be passed off to a plugin or external helper app