Fix Open/Save dialog and use of hidden browser when saving file types not handled natively using "Save Link as Zotero Snapshot" or drag-and-drop to create a standalone item
This need testing.
This commit is contained in:
parent
8712f49426
commit
017342a85e
4 changed files with 344 additions and 211 deletions
|
@ -628,16 +628,16 @@ var ZoteroPane = new function()
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!this.canEdit(row)) {
|
|
||||||
this.displayCannotEditLibraryMessage();
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Currently selected row
|
// Currently selected row
|
||||||
if (row === undefined) {
|
if (row === undefined) {
|
||||||
row = this.collectionsView.selection.currentIndex;
|
row = this.collectionsView.selection.currentIndex;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (!this.canEdit(row)) {
|
||||||
|
this.displayCannotEditLibraryMessage();
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
if (row !== undefined) {
|
if (row !== undefined) {
|
||||||
var itemGroup = this.collectionsView._getItemAtRow(row);
|
var itemGroup = this.collectionsView._getItemAtRow(row);
|
||||||
var libraryID = itemGroup.ref.libraryID;
|
var libraryID = itemGroup.ref.libraryID;
|
||||||
|
@ -2255,30 +2255,6 @@ var ZoteroPane = new function()
|
||||||
* regardless of automaticSnapshots pref
|
* regardless of automaticSnapshots pref
|
||||||
*/
|
*/
|
||||||
this.addItemFromDocument = function (doc, itemType, saveSnapshot, row) {
|
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();
|
var progressWin = new Zotero.ProgressWindow();
|
||||||
progressWin.changeHeadline(Zotero.getString('ingester.scraping'));
|
progressWin.changeHeadline(Zotero.getString('ingester.scraping'));
|
||||||
var icon = 'chrome://zotero/skin/treeitem-webpage.png';
|
var icon = 'chrome://zotero/skin/treeitem-webpage.png';
|
||||||
|
@ -2286,12 +2262,6 @@ var ZoteroPane = new function()
|
||||||
progressWin.show();
|
progressWin.show();
|
||||||
progressWin.startCloseTimer();
|
progressWin.startCloseTimer();
|
||||||
|
|
||||||
var data = {
|
|
||||||
title: doc.title,
|
|
||||||
url: doc.location.href,
|
|
||||||
accessDate: "CURRENT_TIMESTAMP"
|
|
||||||
}
|
|
||||||
|
|
||||||
// TODO: this, needless to say, is a temporary hack
|
// TODO: this, needless to say, is a temporary hack
|
||||||
if (itemType == 'temporaryPDFHack') {
|
if (itemType == 'temporaryPDFHack') {
|
||||||
itemType = null;
|
itemType = null;
|
||||||
|
@ -2315,6 +2285,36 @@ var ZoteroPane = new function()
|
||||||
}
|
}
|
||||||
|
|
||||||
if (isPDF) {
|
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) {
|
if (libraryID) {
|
||||||
var pr = Components.classes["@mozilla.org/network/default-prompt;1"]
|
var pr = Components.classes["@mozilla.org/network/default-prompt;1"]
|
||||||
.getService(Components.interfaces.nsIPrompt);
|
.getService(Components.interfaces.nsIPrompt);
|
||||||
|
@ -2328,6 +2328,7 @@ var ZoteroPane = new function()
|
||||||
else {
|
else {
|
||||||
var collectionID = false;
|
var collectionID = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
Zotero.Attachments.importFromDocument(doc, false, false, collectionID);
|
Zotero.Attachments.importFromDocument(doc, false, false, collectionID);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
@ -2337,6 +2338,11 @@ var ZoteroPane = new function()
|
||||||
if (!itemType) {
|
if (!itemType) {
|
||||||
itemType = 'webpage';
|
itemType = 'webpage';
|
||||||
}
|
}
|
||||||
|
var data = {
|
||||||
|
title: doc.title,
|
||||||
|
url: doc.location.href,
|
||||||
|
accessDate: "CURRENT_TIMESTAMP"
|
||||||
|
}
|
||||||
itemType = Zotero.ItemTypes.getID(itemType);
|
itemType = Zotero.ItemTypes.getID(itemType);
|
||||||
var item = this.newItem(itemType, data, row);
|
var item = this.newItem(itemType, data, row);
|
||||||
|
|
||||||
|
@ -2369,17 +2375,113 @@ var ZoteroPane = new function()
|
||||||
return this.addItemFromPage(itemType, saveSnapshot, row);
|
return this.addItemFromPage(itemType, saveSnapshot, row);
|
||||||
}
|
}
|
||||||
|
|
||||||
var processor = function (doc) {
|
Zotero.MIME.getMIMETypeFromURL(url, function (mimeType, hasNativeHandler) {
|
||||||
ZoteroPane.addItemFromDocument(doc, itemType, saveSnapshot, row);
|
// If native type, save using a hidden browser
|
||||||
};
|
if (hasNativeHandler) {
|
||||||
|
var processor = function (doc) {
|
||||||
var done = function () {}
|
ZoteroPane.addItemFromDocument(doc, itemType, saveSnapshot, row);
|
||||||
|
};
|
||||||
var exception = function (e) {
|
|
||||||
Zotero.debug(e);
|
var done = function () {}
|
||||||
}
|
|
||||||
|
var exception = function (e) {
|
||||||
Zotero.Utilities.HTTP.processDocuments([url], processor, done, exception);
|
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;
|
||||||
|
|
||||||
|
}
|
||||||
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -63,7 +63,7 @@
|
||||||
<!-- TODO: localize and remove zotero.contextMenu.saveLinkAsItem/saveImageAsSnapshot -->
|
<!-- TODO: localize and remove zotero.contextMenu.saveLinkAsItem/saveImageAsSnapshot -->
|
||||||
<menuitem id="zotero-context-save-link-as-item" class="menu-iconic"
|
<menuitem id="zotero-context-save-link-as-item" class="menu-iconic"
|
||||||
label="Save Link as Zotero Item" hidden="true"
|
label="Save Link as Zotero Item" hidden="true"
|
||||||
oncommand="ZoteroPane.addItemFromURL(window.gContextMenu.linkURL)"/>
|
oncommand="ZoteroPane.addItemFromURL(window.gContextMenu.linkURL, 'temporaryPDFHack')"/>
|
||||||
<menuitem id="zotero-context-save-image-as-item" class="menu-iconic"
|
<menuitem id="zotero-context-save-image-as-item" class="menu-iconic"
|
||||||
label="Save Image as Zotero Item" hidden="true"
|
label="Save Image as Zotero Item" hidden="true"
|
||||||
oncommand="ZoteroPane.addItemFromURL(window.gContextMenu.onImage ? (window.gContextMenu.mediaURL ? window.gContextMenu.mediaURL : window.gContextMenu.imageURL) : window.gContextMenu.bgImageURL, 'artwork')"/>
|
oncommand="ZoteroPane.addItemFromURL(window.gContextMenu.onImage ? (window.gContextMenu.mediaURL ? window.gContextMenu.mediaURL : window.gContextMenu.imageURL) : window.gContextMenu.bgImageURL, 'artwork')"/>
|
||||||
|
|
|
@ -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');
|
Zotero.debug('Importing attachment from URL');
|
||||||
|
|
||||||
if (sourceItemID && parentCollectionIDs) {
|
if (sourceItemID && parentCollectionIDs) {
|
||||||
|
@ -206,180 +206,181 @@ Zotero.Attachments = new function(){
|
||||||
throw ("Invalid URL '" + url + "' in Zotero.Attachments.importFromURL()");
|
throw ("Invalid URL '" + url + "' in Zotero.Attachments.importFromURL()");
|
||||||
}
|
}
|
||||||
|
|
||||||
Zotero.Utilities.HTTP.doHead(url, function(obj){
|
// Save using a hidden browser
|
||||||
if (obj.status != 200 && obj.status != 204) {
|
var nativeHandlerImport = function () {
|
||||||
Zotero.debug("Attachment HEAD request returned with status code "
|
var browser = Zotero.Browser.createHiddenBrowser();
|
||||||
+ obj.status + " in Attachments.importFromURL()", 2);
|
var imported = false;
|
||||||
var mimeType = '';
|
var onpageshow = function() {
|
||||||
}
|
// ignore spurious about:blank loads
|
||||||
else {
|
if(browser.contentDocument.location.href == "about:blank") return;
|
||||||
var mimeType = obj.channel.contentType;
|
|
||||||
}
|
// pageshow can be triggered multiple times on some pages,
|
||||||
|
// so make sure we only import once
|
||||||
var nsIURL = Components.classes["@mozilla.org/network/standard-url;1"]
|
// (https://www.zotero.org/trac/ticket/795)
|
||||||
.createInstance(Components.interfaces.nsIURL);
|
if (imported) {
|
||||||
nsIURL.spec = url;
|
return;
|
||||||
|
}
|
||||||
// Override MIME type to application/pdf if extension is .pdf --
|
var callback = function () {
|
||||||
// workaround for sites that respond to the HEAD request with an
|
browser.removeEventListener("pageshow", onpageshow, false);
|
||||||
// invalid MIME type (https://www.zotero.org/trac/ticket/460)
|
Zotero.Browser.deleteHiddenBrowser(browser);
|
||||||
//
|
|
||||||
// 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;
|
|
||||||
};
|
};
|
||||||
browser.addEventListener("pageshow", onpageshow, false);
|
Zotero.Attachments.importFromDocument(browser.contentDocument,
|
||||||
browser.loadURI(url);
|
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
|
var title = forceTitle ? forceTitle : fileName;
|
||||||
else {
|
|
||||||
if (forceFileBaseName) {
|
const nsIWBP = Components.interfaces.nsIWebBrowserPersist;
|
||||||
var ext = _getExtensionFromURL(url, mimeType);
|
var wbp = Components
|
||||||
var fileName = forceFileBaseName + (ext != '' ? '.' + ext : '');
|
.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 {
|
attachmentItem.setField('title', title);
|
||||||
var fileName = _getFileNameFromURL(url, mimeType);
|
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 file = destDir.clone();
|
||||||
var wbp = Components
|
file.append(fileName);
|
||||||
.classes["@mozilla.org/embedding/browser/nsWebBrowserPersist;1"]
|
|
||||||
.createInstance(nsIWBP);
|
|
||||||
wbp.persistFlags = nsIWBP.PERSIST_FLAGS_AUTODETECT_APPLY_CONVERSION;
|
|
||||||
var encodingFlags = false;
|
|
||||||
|
|
||||||
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 {
|
try {
|
||||||
// Create a new attachment
|
// Clean up
|
||||||
var attachmentItem = new Zotero.Item('attachment');
|
if (itemID) {
|
||||||
if (sourceItemID) {
|
var itemDir = this.getStorageDirectory(itemID);
|
||||||
var parentItem = Zotero.Items.get(sourceItemID);
|
if (itemDir.exists()) {
|
||||||
attachmentItem.libraryID = parentItem.libraryID;
|
itemDir.remove(true);
|
||||||
}
|
|
||||||
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);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// 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 (!mimeType) {
|
||||||
// If we don't have the MIME type, do a HEAD request for it
|
// If we don't have the MIME type, do a HEAD request for it
|
||||||
Zotero.Utilities.HTTP.doHead(url, function(obj){
|
Zotero.MIME.getMIMETypeFromURL(url, function (mimeType) {
|
||||||
var mimeType = obj.channel.contentType;
|
|
||||||
|
|
||||||
if (mimeType) {
|
if (mimeType) {
|
||||||
var disabled = Zotero.Notifier.disable();
|
var disabled = Zotero.Notifier.disable();
|
||||||
|
|
||||||
|
|
|
@ -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
|
* Determine if a MIME type can be handled natively
|
||||||
* or if it needs to be passed off to a plugin or external helper app
|
* or if it needs to be passed off to a plugin or external helper app
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue