diff --git a/chrome/content/zotero/webpagedump/common.js b/chrome/content/zotero/webpagedump/common.js index b618eca02..2e290d06b 100644 --- a/chrome/content/zotero/webpagedump/common.js +++ b/chrome/content/zotero/webpagedump/common.js @@ -54,6 +54,8 @@ var WPD_DEFAULTHEIGHT = 768; var WPD_MAXUIERRORCOUNT = 8; +// maximum character length for a valid file name (excluding extension) +var WPD_MAX_FILENAME_LENGTH = 100; /*function wpdGetTopBrowserWindow() { @@ -353,15 +355,10 @@ var wpdCommon = { }, // replace illegal characters + // and shorten long file names getValidFileName: function (aFileName) { - aFileName = aFileName.replace(/[\"\?!~`]+/g, ""); - aFileName = aFileName.replace(/[\*\&]+/g, "+"); - aFileName = aFileName.replace(/[\\\/\|\:;]+/g, "-"); - aFileName = aFileName.replace(/[\<]+/g, "("); - aFileName = aFileName.replace(/[\>]+/g, ")"); - aFileName = aFileName.replace(/[\s]+/g, "_"); - aFileName = aFileName.replace(/[%]+/g, "@"); - return aFileName; + aFileName = Zotero.File.getValidFileName(aFileName); + return Zotero.File.truncateFileName(aFileName, WPD_MAX_FILENAME_LENGTH); }, getURL: function () { diff --git a/chrome/content/zotero/webpagedump/domsaver.js b/chrome/content/zotero/webpagedump/domsaver.js index 4bad0d611..d7b38d6ea 100644 --- a/chrome/content/zotero/webpagedump/domsaver.js +++ b/chrome/content/zotero/webpagedump/domsaver.js @@ -164,7 +164,8 @@ var wpdDOMSaver = { // Split fileName in Path and Name - this.name = wpdCommon.getFileLeafName(fileName); // extract fileName from filePath + this.name = wpdCommon.getValidFileName( + wpdCommon.getFileLeafName(fileName)); // extract fileName from filePath this.currentDir = wpdCommon.getFilePath(fileName); // only directory this.name = wpdCommon.splitFileName(this.name)[0]; // no extension! @@ -221,7 +222,7 @@ var wpdDOMSaver = { // resolve the javascript links inside the attributes (e.g. onclick,...) normalizeJavaScriptLink: function (aNode, aAttr) { var val = aNode.getAttribute(aAttr); // get the attribute value and check for link stuff - if (!val.match(/\(\'([^\']+)\'/)) return aNode; + if (!val || !val.match(/\(\'([^\']+)\'/)) return aNode; val = RegExp.$1; if (val.indexOf("/") == -1 && val.indexOf(".") == -1) return aNode; val = wpdCommon.resolveURL(this.currentURL, val); // it is a link -> resolve and set the URL to the local URL @@ -409,9 +410,12 @@ var wpdDOMSaver = { case "link": // could containt urls (icon, stylesheet and fontdef) // We have to remove nodes with the stylesheet attribute because they will be added later - if ((aNode.getAttribute("rel").toLowerCase() == "stylesheet") && (aNode.getAttribute("href").indexOf("chrome://") == -1)) { + if(!aNode.hasAttribute("rel")) return aNode; + if (aNode.getAttribute("rel").toLowerCase() == "stylesheet" + && (aNode.hasAttribute("href") && aNode.getAttribute("href").indexOf("chrome://") == -1)) { return wpdCommon.removeNodeFromParent(aNode); - } else if ((aNode.getAttribute("rel").toLowerCase() == "shortcut icon") || (aNode.getAttribute("rel").toLowerCase() == "icon")) { + } else if (aNode.getAttribute("rel").toLowerCase() == "shortcut icon" + || aNode.getAttribute("rel").toLowerCase() == "icon") { var aFileName = this.download(aNode.href, true); // Changed by Dan S. for Zotero -- see this.repairRelativeLinks() if (aFileName) aNode.setAttribute("href", this.relativeLinkFix(aFileName)); @@ -671,7 +675,7 @@ var wpdDOMSaver = { //returns a unique file name and registers it getUniqueFileNameAndRegister: function(fileName, sourceURL, content) { fileName = this.checkForEqualFilenames( - wpdCommon.getValidFileName(fileName).toLowerCase(), + wpdCommon.getValidFileName(fileName), sourceURL); this.registerFile(fileName, sourceURL, content); return fileName; @@ -679,7 +683,7 @@ var wpdDOMSaver = { //register filename, so we don't overwrite them later registerFile: function (newFileName, sourceURL, content) { - this.fileInfo[newFileName] = { + this.fileInfo[newFileName.toLowerCase()] = { url: sourceURL, downloaded: content } @@ -687,11 +691,12 @@ var wpdDOMSaver = { // is the file registered (e.g. downloaded)? isFileRegistered: function (newFileName) { - if (this.fileInfo[newFileName] != undefined) return true; + if (this.fileInfo[newFileName.toLowerCase()] != undefined) return true; return false; }, isDownloaded: function(fileName) { + fileName = fileName.toLowerCase(); if(!this.fileInfo[fileName]) return; return this.fileInfo[fileName].downloaded; }, @@ -701,16 +706,16 @@ var wpdDOMSaver = { // if no aURLSpec is passed, this generates a unique file name checkForEqualFilenames: function (newFileName, aURLSpec) { if (this.isFileRegistered(newFileName)) { - if (!aURLSpec || this.fileInfo[newFileName]["url"] != aURLSpec) { + if (!aURLSpec || this.fileInfo[newFileName.toLowerCase()]["url"] != aURLSpec) { // the file is already registered but from a different location // => probably not the same file, so we have to find a different name it (e.g. filename_001.ext) var seq = 1; var fileLR = wpdCommon.splitFileName(newFileName); if (!fileLR[1]) fileLR[1] = "dat"; newFileName = fileLR[0] + "_" + wpdCommon.addLeftZeros(seq++, 3) + "." + fileLR[1]; - while (this.fileInfo[newFileName] != undefined) { + while (this.fileInfo[newFileName.toLowerCase()] != undefined) { // is the file already registered with the new name? - if (aURLSpec && this.fileInfo[newFileName]["url"] == aURLSpec) return newFileName; // Yes -> so it�s already downloaded and we are finished + if (aURLSpec && this.fileInfo[newFileName.toLowerCase()]["url"] == aURLSpec) return newFileName; // Yes -> so it's already downloaded and we are finished newFileName = fileLR[0] + "_" + wpdCommon.addLeftZeros(seq++, 3) + "." + fileLR[1]; // No -> "increment" filename } } @@ -730,9 +735,8 @@ var wpdDOMSaver = { var aURL = wpdCommon.convertURLToObject(aURLSpec); // generate a filename - var newFileName = aURL.fileName.toLowerCase(); + var newFileName = aURL.fileName; if (!newFileName) newFileName = "untitled"; - newFileName = wpdCommon.getValidFileName(newFileName); // same name but different location? newFileName = this.getUniqueFileNameAndRegister(newFileName, aURLSpec); // is the file already registered (processed) ? @@ -1076,7 +1080,7 @@ var wpdDOMSaver = { // (be sure to call the init function at the top of this file before) saveHTMLDocument: function () { try { - this.saveDocumentEx(this.document, this.name); + return this.saveDocumentEx(this.document, this.name); } catch (ex) { wpdCommon.addError("[wpdDOMSaver.saveHTMLDocument]\n -> " + ex); } diff --git a/chrome/content/zotero/xpcom/attachments.js b/chrome/content/zotero/xpcom/attachments.js index 952be591d..4d4be86e1 100644 --- a/chrome/content/zotero/xpcom/attachments.js +++ b/chrome/content/zotero/xpcom/attachments.js @@ -234,7 +234,7 @@ Zotero.Attachments = new function(){ }; Zotero.Attachments.importFromDocument(browser.contentDocument, sourceItemID, forceTitle, parentCollectionIDs, importCallback, libraryID); - }, undefined, undefined, true); + }, undefined, undefined, true, cookieSandbox); }; // Save using remote web browser persist @@ -550,10 +550,13 @@ Zotero.Attachments = new function(){ var file = Components.classes["@mozilla.org/file/local;1"]. createInstance(Components.interfaces.nsILocalFile); file.initWithFile(destDir); - - var fileName = _getFileNameFromURL(url, mimeType); - file.append(fileName); - + + var fileName = Zotero.File.truncateFileName( + _getFileNameFromURL(url, mimeType), + 100 //make sure this matches WPD settings in webpagedump/common.js + ); + file.append(fileName) + if (mimeType == 'application/pdf') { var f = function() { Zotero.Fulltext.indexPDF(file, itemID); @@ -581,10 +584,10 @@ Zotero.Attachments = new function(){ Components.classes["@mozilla.org/moz/jssubscript-loader;1"] .getService(Components.interfaces.mozIJSSubScriptLoader) .loadSubScript("chrome://zotero/content/webpagedump/domsaver.js", wpd); - + wpd.wpdDOMSaver.init(file.path, document); wpd.wpdDOMSaver.saveHTMLDocument(); - + attachmentItem.attachmentPath = this.getPath( file, Zotero.Attachments.LINK_MODE_IMPORTED_URL ); @@ -1178,26 +1181,24 @@ Zotero.Attachments = new function(){ nsIURL.fileBaseName = nsIURL.fileBaseName + '.' + tld; } - // Unencode fileBaseName - var decodedFileBaseName; + // Test unencoding fileBaseName try { - decodedFileBaseName = decodeURIComponent(nsIURL.fileBaseName); + decodeURIComponent(nsIURL.fileBaseName); } catch (e) { if (e.name == 'URIError') { // If we got a 'malformed URI sequence' while decoding, - // try MD5 (in hex string) of fileBaseName. - decodedFileBaseName = Zotero.Utilities.Internal.md5(nsIURL.fileBaseName, false); + // use MD5 of fileBaseName + nsIURL.fileBaseName = Zotero.Utilities.Internal.md5(nsIURL.fileBaseName, false); } else { throw e; } } - // Pass unencoded name to getValidFileName() so that '%20' isn't stripped to '20' - nsIURL.fileBaseName = Zotero.File.getValidFileName(decodedFileBaseName); - - return decodeURIComponent(nsIURL.fileName); + // Pass unencoded name to getValidFileName() so that percent-encoded + // characters aren't stripped to just numbers + return Zotero.File.getValidFileName(decodeURIComponent(nsIURL.fileName)); } diff --git a/chrome/content/zotero/xpcom/cookieSandbox.js b/chrome/content/zotero/xpcom/cookieSandbox.js index e17a7423f..0d013ad91 100755 --- a/chrome/content/zotero/xpcom/cookieSandbox.js +++ b/chrome/content/zotero/xpcom/cookieSandbox.js @@ -102,7 +102,8 @@ Zotero.CookieSandbox.prototype = { * @param {nsIInterfaceRequestor} ir */ "attachToInterfaceRequestor": function(ir) { - Zotero.CookieSandbox.Observer.trackedInterfaceRequestors.set(ir.QueryInterface(Components.interfaces.nsIInterfaceRequestor), this); + Zotero.CookieSandbox.Observer.trackedInterfaceRequestors.push(Components.utils.getWeakReference(ir.QueryInterface(Components.interfaces.nsIInterfaceRequestor))); + Zotero.CookieSandbox.Observer.trackedInterfaceRequestorSandboxes.push(this); } } @@ -125,7 +126,8 @@ Zotero.CookieSandbox.Observer = new function() { */ this.register = function(CookieSandbox) { this.trackedBrowsers = new WeakMap(); - this.trackedInterfaceRequestors = new WeakMap(); + this.trackedInterfaceRequestors = []; + this.trackedInterfaceRequestorSandboxes = []; if(!observing) { Zotero.debug("CookieSandbox: Registering observers"); @@ -145,7 +147,21 @@ Zotero.CookieSandbox.Observer = new function() { // try the notification callbacks if(notificationCallbacks) { - trackedBy = this.trackedInterfaceRequestors.get(notificationCallbacks); + for(var i=0; i]/g, ''); // Replace newlines and tabs (which shouldn't be in the string in the first place) with spaces - fileName = fileName.replace(/[\n\t]/g, ' '); + fileName = fileName.replace(/[\r\n\t]+/g, ' '); // Replace various thin spaces fileName = fileName.replace(/[\u2000-\u200A]/g, ' '); // Replace zero-width spaces @@ -289,13 +290,44 @@ Zotero.File = new function(){ // Strip characters not valid in XML, since they won't sync and they're probably unwanted fileName = fileName.replace(/[\u0000-\u0008\u000b\u000c\u000e-\u001f\ud800-\udfff\ufffe\uffff]/g, ''); } - // Don't allow blank filename - if (!fileName) { + // Don't allow blank or illegal filenames + if (!fileName || fileName == '.' || fileName == '..') { fileName = '_'; } return fileName; } + /** + * Truncate a filename (excluding the extension) to the given total length + * If the "extension" is longer than 20 characters, + * it is treated as part of the file name + */ + function truncateFileName(fileName, maxLength) { + if(!fileName || (fileName + '').length <= maxLength) return fileName; + + var parts = (fileName + '').split(/\.(?=[^\.]+$)/); + var fn = parts[0]; + var ext = parts[1]; + //if the file starts with a period , use the whole file + //the whole file name might also just be a period + if(!fn) { + fn = '.' + (ext || ''); + } + + //treat long extensions as part of the file name + if(ext && ext.length > 20) { + fn += '.' + ext; + ext = undefined; + } + + if(ext === undefined) { //there was no period in the whole file name + ext = ''; + } else { + ext = '.' + ext; + } + + return fn.substr(0,maxLength-ext.length) + ext; + } /* * Not implemented, but it'd sure be great if it were diff --git a/chrome/content/zotero/xpcom/http.js b/chrome/content/zotero/xpcom/http.js index 5468cc4e7..7e476663c 100644 --- a/chrome/content/zotero/xpcom/http.js +++ b/chrome/content/zotero/xpcom/http.js @@ -185,7 +185,7 @@ Zotero.HTTP = new function() { _stateChange(xmlhttp, onDone, responseCharset); }; - if(cookieSandbox) cookieSandbox.attachToInterfaceRequestor(xmlhttp); + if(cookieSandbox) cookieSandbox.attachToInterfaceRequestor(xmlhttp.getInterface(Components.interfaces.nsIInterfaceRequestor)); xmlhttp.send(null); return xmlhttp; @@ -273,7 +273,7 @@ Zotero.HTTP = new function() { _stateChange(xmlhttp, onDone, responseCharset); }; - if(cookieSandbox) cookieSandbox.attachToInterfaceRequestor(xmlhttp); + if(cookieSandbox) cookieSandbox.attachToInterfaceRequestor(xmlhttp.getInterface(Components.interfaces.nsIInterfaceRequestor)); xmlhttp.send(body); return xmlhttp; @@ -337,7 +337,7 @@ Zotero.HTTP = new function() { _stateChange(xmlhttp, onDone); }; - if(cookieSandbox) cookieSandbox.attachToInterfaceRequestor(xmlhttp); + if(cookieSandbox) cookieSandbox.attachToInterfaceRequestor(xmlhttp.getInterface(Components.interfaces.nsIInterfaceRequestor)); xmlhttp.send(null); return xmlhttp; diff --git a/chrome/content/zotero/xpcom/report.js b/chrome/content/zotero/xpcom/report.js index 5fe02b17d..0f75faf4e 100644 --- a/chrome/content/zotero/xpcom/report.js +++ b/chrome/content/zotero/xpcom/report.js @@ -35,9 +35,8 @@ Zotero.Report = new function() { function generateHTMLDetails(items, combineChildItems) { - var content = '\n'; - content += '\n'; + var content = '\n'; + content += '\n'; content += '\n'; content += '' + Zotero.getString('report.title.default') + '\n'; content += '\n'; @@ -74,8 +73,9 @@ Zotero.Report = new function() { // If not valid XML, display notes with entities encoded var parser = Components.classes["@mozilla.org/xmlextras/domparser;1"] .createInstance(Components.interfaces.nsIDOMParser); - var doc = parser.parseFromString(arr.note, "application/xml"); + var doc = parser.parseFromString('
' + arr.note.replace(/ /g, " ") + '
', "application/xml"); if (doc.documentElement.tagName == 'parsererror') { + Zotero.debug(doc.documentElement.textContent, 2); content += '

' + escapeXML(arr.note) + '

\n'; } // Otherwise render markup normally @@ -100,8 +100,9 @@ Zotero.Report = new function() { // If not valid XML, display notes with entities encoded var parser = Components.classes["@mozilla.org/xmlextras/domparser;1"] .createInstance(Components.interfaces.nsIDOMParser); - var doc = parser.parseFromString(note.note, "application/xml"); + var doc = parser.parseFromString('
' + note.note.replace(/ /g, " ") + '
', "application/xml"); if (doc.documentElement.tagName == 'parsererror') { + Zotero.debug(doc.documentElement.textContent, 2); content += '

' + escapeXML(note.note) + '

\n'; } // Otherwise render markup normally diff --git a/chrome/content/zotero/xpcom/translation/translate_firefox.js b/chrome/content/zotero/xpcom/translation/translate_firefox.js index 7ea406311..0635544d1 100644 --- a/chrome/content/zotero/xpcom/translation/translate_firefox.js +++ b/chrome/content/zotero/xpcom/translation/translate_firefox.js @@ -434,7 +434,7 @@ Zotero.Translate.SandboxManager = function(sandboxLocation) { }; }; this.sandbox.XMLSerializer.__exposedProps__ = {"prototype":"r"}; - this.sandbox.XMLSerializer.prototype = {}; + this.sandbox.XMLSerializer.prototype = {"__exposedProps__":{"serializeToString":"r"}}; } Zotero.Translate.SandboxManager.prototype = { diff --git a/chrome/content/zotero/xpcom/zotero.js b/chrome/content/zotero/xpcom/zotero.js index f8325eb05..4ad7c778e 100644 --- a/chrome/content/zotero/xpcom/zotero.js +++ b/chrome/content/zotero/xpcom/zotero.js @@ -35,7 +35,7 @@ const ZOTERO_CONFIG = { API_URL: 'https://api.zotero.org/', PREF_BRANCH: 'extensions.zotero.', BOOKMARKLET_URL: 'https://www.zotero.org/bookmarklet/', - VERSION: "3.0.10.SOURCE" + VERSION: "3.0.11.SOURCE" }; // Commonly used imports accessible anywhere diff --git a/chrome/content/zotero/zoteroPane.js b/chrome/content/zotero/zoteroPane.js index c8fa78897..77f21169d 100644 --- a/chrome/content/zotero/zoteroPane.js +++ b/chrome/content/zotero/zoteroPane.js @@ -2652,22 +2652,25 @@ var ZoteroPane = new function() } } else if (tree.id == 'zotero-items-tree') { - // Expand/collapse on triple-click - if (!Zotero.Prefs.get('viewOnDoubleClick')) { - return; + var viewOnDoubleClick = Zotero.Prefs.get('viewOnDoubleClick'); + if (viewOnDoubleClick) { + // Expand/collapse on triple-click, though the double-click + // will still trigger + if (event.detail == 3) { + tree.view.toggleOpenState(tree.view.selection.currentIndex); + return; + } + + // Don't expand/collapse on double-click + event.stopPropagation(); } - if (event.detail == 3) { - tree.view.toggleOpenState(tree.view.selection.currentIndex); - return; - } - - // Don't expand/collapse on double-click - event.stopPropagation(); - if (tree.view && tree.view.selection.currentIndex > -1) { var item = ZoteroPane_Local.getSelectedItems()[0]; if (item) { + if (!viewOnDoubleClick && item.isRegularItem()) { + return; + } ZoteroPane_Local.viewItems([item], event); } } diff --git a/components/zotero-protocol-handler.js b/components/zotero-protocol-handler.js index c99d99195..a864e29d4 100644 --- a/components/zotero-protocol-handler.js +++ b/components/zotero-protocol-handler.js @@ -479,21 +479,7 @@ function ChromeExtensionHandler() { default: var content = Zotero.Report.generateHTMLDetails(items, combineChildItems); - - // Serve invalid XML as text/html - // - // This is a temporary workaround until we figure out - // something better. - try { - var xml = new XML(content.replace(/^<\!DOCTYPE [^>]+>\n/, '').trim()); - mimeType = 'application/xhtml+xml'; - } - catch (e) { - Zotero.debug(e); - mimeType = 'text/html'; - } - - format = 'html'; + mimeType = 'text/html'; } } catch (e){ diff --git a/install.rdf b/install.rdf index 30b6335b2..5795b47c2 100644 --- a/install.rdf +++ b/install.rdf @@ -6,11 +6,7 @@ zotero@chnm.gmu.edu Zotero -<<<<<<< HEAD 3.5a1.SOURCE -======= - 3.0.10.SOURCE ->>>>>>> 3.0 Center for History and New Media
George Mason University
Dan Cohen Sean Takats diff --git a/resource/schema/repotime.txt b/resource/schema/repotime.txt index cbe0afbf9..606f4a2b5 100644 --- a/resource/schema/repotime.txt +++ b/resource/schema/repotime.txt @@ -1 +1 @@ -2012-11-18 22:15:00 +2012-11-22 19:15:00 diff --git a/translators b/translators index 14794d840..2c33d5d46 160000 --- a/translators +++ b/translators @@ -1 +1 @@ -Subproject commit 14794d840b2476cca38cbcd7f17d8c3952a4536d +Subproject commit 2c33d5d461cab0749702529e26686738e7a0b411