Merge branch '3.0'

Conflicts:
	chrome/content/zotero/xpcom/attachments.js
	chrome/content/zotero/xpcom/translation/translate_item.js
	install.rdf
	update.rdf
This commit is contained in:
Dan Stillman 2012-11-23 01:49:32 -05:00
commit 4caae896cf
14 changed files with 121 additions and 85 deletions

View file

@ -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 () {

View file

@ -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<EFBFBD>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);
}

View file

@ -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));
}

View file

@ -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<this.trackedInterfaceRequestors.length; i++) {
// Interface requestors are stored as weak references, so we have to see
// if they still point to something
var ir = this.trackedInterfaceRequestors[i].get();
if(!ir) {
// The interface requestor is gone, so remove it from the list
this.trackedInterfaceRequestors.splice(i--, 1);
this.trackedInterfaceRequestorSandboxes.splice(i--, 1);
} else if(ir == notificationCallbacks) {
// We are tracking this interface requestor
trackedBy = this.trackedInterfaceRequestorSandboxes[i];
break;
}
}
if(trackedBy) {
tested = true;
} else {

View file

@ -38,6 +38,7 @@ Zotero.File = new function(){
this.getContentsFromURL = getContentsFromURL;
this.putContents = putContents;
this.getValidFileName = getValidFileName;
this.truncateFileName = truncateFileName;
this.copyToUnique = this.copyToUnique;
this.getCharsetFromFile = getCharsetFromFile;
this.addCharsetListener = addCharsetListener;
@ -280,7 +281,7 @@ Zotero.File = new function(){
// URL encode when saving attachments that trigger this
fileName = fileName.replace(/[\/\\\?%\*:|"<>]/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

View file

@ -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;

View file

@ -35,9 +35,8 @@ Zotero.Report = new function() {
function generateHTMLDetails(items, combineChildItems) {
var content = '<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" ';
content += '"http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">\n';
content += '<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en">\n';
var content = '<!DOCTYPE html>\n';
content += '<html>\n';
content += '<head><meta http-equiv="Content-Type" content="text/html; charset=utf-8" />\n';
content += '<title>' + Zotero.getString('report.title.default') + '</title>\n';
content += '<link rel="stylesheet" type="text/css" href="zotero://report/detail.css"/>\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('<div>' + arr.note.replace(/&nbsp;/g, "&#160;") + '</div>', "application/xml");
if (doc.documentElement.tagName == 'parsererror') {
Zotero.debug(doc.documentElement.textContent, 2);
content += '<p class="plaintext">' + escapeXML(arr.note) + '</p>\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('<div>' + note.note.replace(/&nbsp;/g, "&#160;") + '</div>', "application/xml");
if (doc.documentElement.tagName == 'parsererror') {
Zotero.debug(doc.documentElement.textContent, 2);
content += '<p class="plaintext">' + escapeXML(note.note) + '</p>\n';
}
// Otherwise render markup normally

View file

@ -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 = {

View file

@ -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

View file

@ -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);
}
}

View file

@ -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){

View file

@ -6,11 +6,7 @@
<em:id>zotero@chnm.gmu.edu</em:id>
<em:name>Zotero</em:name>
<<<<<<< HEAD
<em:version>3.5a1.SOURCE</em:version>
=======
<em:version>3.0.10.SOURCE</em:version>
>>>>>>> 3.0
<em:creator>Center for History and New Media<br/>George Mason University</em:creator>
<em:contributor>Dan Cohen</em:contributor>
<em:contributor>Sean Takats</em:contributor>

View file

@ -1 +1 @@
2012-11-18 22:15:00
2012-11-22 19:15:00

@ -1 +1 @@
Subproject commit 14794d840b2476cca38cbcd7f17d8c3952a4536d
Subproject commit 2c33d5d461cab0749702529e26686738e7a0b411