From da18408070e7aef247c2cac25ab4ad2e0d3072a2 Mon Sep 17 00:00:00 2001 From: Dan Stillman Date: Sat, 19 Mar 2016 02:46:29 -0400 Subject: [PATCH 1/6] Fix proxy redirection in Firefox 46 (non-e10s) notificationCallbacks no longer QIs to webNavigation in Firefox 46, so this gets the relevant browser object by getting the content window id from channel.loadInfo and finding the window via nsIWindowMediator. Unfortunately the window id provided under e10s is invalid (or something -- it's a very high number that can't be found via nsIWindowMediator), so something else will need to be done for that. --- chrome/content/zotero/xpcom/proxy.js | 97 +++++++++++++++++----------- 1 file changed, 58 insertions(+), 39 deletions(-) diff --git a/chrome/content/zotero/xpcom/proxy.js b/chrome/content/zotero/xpcom/proxy.js index 2de3b54b8d..d35b2cd738 100644 --- a/chrome/content/zotero/xpcom/proxy.js +++ b/chrome/content/zotero/xpcom/proxy.js @@ -82,7 +82,17 @@ Zotero.Proxies = new function() { // try to detect a proxy channel.QueryInterface(Components.interfaces.nsIHttpChannel); var url = channel.URI.spec; - + + try { + var { browser, window } = _getBrowserAndWindow(channel); + } + catch (e) { + Zotero.logError(e); + } + if (!browser) { + Zotero.debug("Couldn't get browser from channel", 2); + } + // see if there is a proxy we already know var m = false; var proxy; @@ -105,13 +115,16 @@ Zotero.Proxies = new function() { proxy.hosts.push(host); proxy.save(true); - var bw = _getBrowserAndWindow(channel.notificationCallbacks); - if(!bw) return; - _showNotification(bw, + if (!browser) return; + _showNotification( + browser, + window, Zotero.getString('proxies.notification.associated.label', [host, channel.URI.hostPort]), [{ label: "proxies.notification.settings.button", callback: function() { _prefsOpenCallback(bw[1]); } }]); } } else { + if (!browser) return; + // otherwise, try to detect a proxy var proxy = false; for(var detectorName in Zotero.Proxies.Detectors) { @@ -126,13 +139,12 @@ Zotero.Proxies = new function() { Zotero.debug("Proxies: Detected "+detectorName+" proxy "+proxy.scheme+ (proxy.multiHost ? " (multi-host)" : " for "+proxy.hosts[0])); - var bw = _getBrowserAndWindow(channel.notificationCallbacks); - if(!bw) return; - var savedTransparent = false; if(Zotero.Proxies.autoRecognize) { // Ask to save only if automatic proxy recognition is on - savedTransparent = _showNotification(bw, + savedTransparent = _showNotification( + browser, + window, Zotero.getString('proxies.notification.recognized.label', [proxy.hosts[0], channel.URI.hostPort]), [{ label: "proxies.notification.enable.button", callback: function() { _showDialog(proxy.hosts[0], channel.URI.hostPort, proxy); } }]); } @@ -144,16 +156,13 @@ Zotero.Proxies = new function() { } // try to get an applicable proxy - var webNav = null; - var docShell = null; - try { - webNav = channel.notificationCallbacks.QueryInterface(Components.interfaces.nsIWebNavigation); - docShell = channel.notificationCallbacks.QueryInterface(Components.interfaces.nsIDocShell); - } catch(e) { + var docShell = browser.docShell; + if (!docShell) { + Zotero.logError("Couldn't get docshell"); return; } - if(!docShell.allowMetaRedirects) return; + if (!docShell || !docShell.allowMetaRedirects) return; // check that proxy redirection is actually enabled if(!Zotero.Proxies.transparent) return; @@ -166,7 +175,6 @@ Zotero.Proxies = new function() { // IP update interval is every 15 minutes if((now - Zotero.Proxies.lastIPCheck) > 900000) { - var notificationCallbacks = channel.notificationCallbacks; Zotero.Proxies.DNS.getHostnames().then(function (hosts) { // if domains necessitate disabling, disable them Zotero.Proxies.disabledByDomain = false; @@ -174,9 +182,9 @@ Zotero.Proxies = new function() { Zotero.Proxies.disabledByDomain = host.toLowerCase().indexOf(Zotero.Proxies.disableByDomain) != -1; if (Zotero.Proxies.disabledByDomain) return; } - _maybeRedirect(channel, notificationCallbacks, proxied); + _maybeRedirect(channel, browser, window, proxied); }, function(e) { - _maybeRedirect(channel, notificationCallbacks, proxied); + _maybeRedirect(channel, browser, window, proxied); }); Zotero.Proxies.lastIPCheck = now; return; @@ -185,16 +193,10 @@ Zotero.Proxies = new function() { if(Zotero.Proxies.disabledByDomain) return; } - _maybeRedirect(channel, channel.notificationCallbacks, proxied); + _maybeRedirect(channel, browser, window, proxied); } - function _maybeRedirect(channel, notificationCallbacks, proxied) { - // try to find a corresponding browser object - var bw = _getBrowserAndWindow(notificationCallbacks); - if(!bw) return; - var browser = bw[0]; - var window = bw[1]; - + function _maybeRedirect(channel, browser, window, proxied) { channel.QueryInterface(Components.interfaces.nsIHttpChannel); var proxiedURI = Components.classes["@mozilla.org/network/io-service;1"] .getService(Components.interfaces.nsIIOService) @@ -242,7 +244,9 @@ Zotero.Proxies = new function() { // Otherwise, redirect. Note that we save the URI we're redirecting from as the // referrer, since we can't make a proper redirect if(Zotero.Proxies.showRedirectNotification) { - _showNotification(bw, + _showNotification( + browser, + window, Zotero.getString('proxies.notification.redirected.label', [channel.URI.hostPort, proxiedURI.hostPort]), [ { label: "general.dontShowAgain", callback: function() { _disableRedirectNotification(); } }, @@ -416,15 +420,33 @@ Zotero.Proxies = new function() { } /** - * Get browser and window from notificationCallbacks - * @return {Array} Array containing a browser object and a DOM window object + * Get browser and window from a channel + * @return {Object} Object containing the content browser as 'browser' and a ChromeWindow as 'window' */ - function _getBrowserAndWindow(notificationCallbacks) { - var browser = notificationCallbacks.getInterface(Ci.nsIWebNavigation) - .QueryInterface(Ci.nsIDocShell).chromeEventHandler; - var window = browser.ownerDocument.defaultView; - return [browser, window]; - } + function _getBrowserAndWindow(channel) { + // Firefox 45 and earlier + if (Zotero.platformMajorVersion < 46) { + var browser = channel.notificationCallbacks.getInterface(Ci.nsIWebNavigation) + .QueryInterface(Ci.nsIDocShell).chromeEventHandler; + } + // Firefox 46 and up (non-e10s) + else { + let outerWindowID = channel.loadInfo.outerWindowID; + var wm = Cc["@mozilla.org/appshell/window-mediator;1"] + .getService(Ci.nsIWindowMediator); + let outerContentWin = wm.getOuterWindowWithId(outerWindowID); + if (!outerContentWin) { + return { browser: null, window: null }; + } + var browser = outerContentWin.QueryInterface(Ci.nsIInterfaceRequestor) + .getInterface(Ci.nsIWebNavigation) + .QueryInterface(Ci.nsIDocShell).chromeEventHandler; + } + return { + browser, + window: browser.ownerDocument.defaultView + }; + } /** * Show a proxy-related notification @@ -432,10 +454,7 @@ Zotero.Proxies = new function() { * @param {String} label notification text * @param {Array} buttons dicts of button label resource string and associated callback */ - function _showNotification(bw, label, buttons) { - var browser = bw[0]; - var window = bw[1]; - + function _showNotification(browser, window, label, buttons) { buttons = buttons.map(function(button) { return { label: Zotero.getString(button.label), From 81e2e926a134d316b76fe80bd5cf1ebba2412e0e Mon Sep 17 00:00:00 2001 From: Dan Stillman Date: Sat, 19 Mar 2016 02:57:10 -0400 Subject: [PATCH 2/6] Update citeproc-js to 1.1.81 --- chrome/content/zotero/xpcom/citeproc.js | 3411 +++++++++++++++-------- 1 file changed, 2315 insertions(+), 1096 deletions(-) diff --git a/chrome/content/zotero/xpcom/citeproc.js b/chrome/content/zotero/xpcom/citeproc.js index d865a2deb6..99810743ce 100644 --- a/chrome/content/zotero/xpcom/citeproc.js +++ b/chrome/content/zotero/xpcom/citeproc.js @@ -1,72 +1,49 @@ + Copyright (c) 2009-2016 Frank Bennett + + This program is free software: you can redistribute it and/or + modify it under EITHER + + * the terms of the Common Public Attribution License (CPAL) as + published by the Open Source Initiative, either version 1 of + the CPAL, or (at your option) any later version; OR + + * the terms of the GNU Affero General Public License (AGPL) + as published by the Free Software Foundation, either version + 3 of the AGPL, or (at your option) any later version. + + This program 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 copies of the Common Public Attribution + License and of the GNU Affero General Public License along with + this program. If not, see or + respectively. + /* - * Copyright (c) 2009-2014 Frank G. Bennett + * Copyright (c) 2009-2016 Frank Bennett * - * Unless otherwise indicated, the files in this repository are subject - * to the Common Public Attribution License Version 1.0 (the “License”); - * you may not use this file except in compliance with the License. You - * may obtain a copy of the License at: + * This program is free software: you can redistribute it and/or + * modify it under EITHER * - * http://bitbucket.org/fbennett/citeproc-js/src/tip/LICENSE. + * * the terms of the Common Public Attribution License (CPAL) as + * published by the Open Source Initiative, either version 1 of + * the CPAL, or (at your option) any later version; OR * - * (See also the note on attribution information below) + * * the terms of the GNU Affero General Public License (AGPL) + * as published by the Free Software Foundation, either version + * 3 of the AGPL, or (at your option) any later version. * - * The License is based on the Mozilla Public License Version 1.1 but - * Sections 1.13, 14 and 15 have been added to cover use of software over a - * computer network and provide for limited attribution for the - * Original Developer. In addition, Exhibit A has been modified to be - * consistent with Exhibit B. + * This program 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. * - * Software distributed under the License is distributed on an “AS IS” - * basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See - * the License for the specific language governing rights and limitations - * under the License. - * - * The Original Code is the citation formatting software known as - * "citeproc-js" (an implementation of the Citation Style Language - * [CSL]), including the original test fixtures and software located - * under the ./tests subdirectory of the distribution archive. - * - * The Original Developer is not the Initial Developer and is - * __________. If left blank, the Original Developer is the Initial - * Developer. - * - * The Initial Developer of the Original Code is Frank Bennett. All - * portions of the code written by Frank Bennett are Copyright (c) - * 2009-2014 Frank Bennett. - * - * *** - * - * Alternatively, the files in this repository may be used under the - * terms of the GNU Affero General Public License (the [AGPLv3] License), - * in which case the provisions of [AGPLv3] License are applicable - * instead of those above. If you wish to allow use of your version of - * this file only under the terms of the [AGPLv3] License and not to - * allow others to use your version of this file under the CPAL, indicate - * your decision by deleting the provisions above and replace them with - * the notice and other provisions required by the [AGPLv3] License. If - * you do not delete the provisions above, a recipient may use your - * version of this file under either the CPAL or the [AGPLv3] License. - * - * *** - * - * Attribution Information (CPAL) - * - * Attribution Copyright Notice: [no separate attribution copyright notice is required] - * - * Attribution Phrase: "Citations by CSL (citeproc-js)" - * - * Attribution URL: http://citationstyles.org/ - * - * Graphic Image: [there is no requirement to display a Graphic Image] - * - * Display of Attribution Information is REQUIRED in Larger Works which - * are defined in the CPAL as a work which combines Covered Code or - * portions thereof with code not governed by the terms of the CPAL. - * - * Display of Attribution Information is also REQUIRED on Associated - * Websites. - * - * [ citeproc-js license :: version 1.1 :: 2012.06.30 ] + * You should have received copies of the Common Public Attribution + * License and of the GNU Affero General Public License along with + * this program. If not, see or + * respectively. */ if (!Array.indexOf) { Array.prototype.indexOf = function (obj) { @@ -80,13 +57,13 @@ if (!Array.indexOf) { }; } var CSL = { - PROCESSOR_VERSION: "1.1.60", + PROCESSOR_VERSION: "1.1.81", CONDITION_LEVEL_TOP: 1, CONDITION_LEVEL_BOTTOM: 2, PLAIN_HYPHEN_REGEX: /(?:[^\\]-|\u2013)/, LOCATOR_LABELS_REGEXP: new RegExp("^((art|ch|subch|col|fig|l|n|no|op|p|pp|para|subpara|pt|r|sec|subsec|sv|sch|tit|vrs|vol)\\.)\\s+(.*)"), - STATUTE_SUBDIV_GROUPED_REGEX: /((?:^| )(?:art|ch|subch|p|pp|para|subpara|pt|r|sec|subsec|sch|tit)\.)/g, - STATUTE_SUBDIV_PLAIN_REGEX: /(?:(?:^| )(?:art|ch|subch|p|pp|para|subpara|pt|r|sec|subsec|sch|tit)\.)/, + STATUTE_SUBDIV_GROUPED_REGEX: /((?:^| )(?:art|bk|ch|subch|col|fig|fol|l|n|no|op|p|pp|para|subpara|pt|r|sec|subsec|sv|sch|tit|vrs|vol)\. *)/g, + STATUTE_SUBDIV_PLAIN_REGEX: /(?:(?:^| )(?:art|bk|ch|subch|col|fig|fol|l|n|no|op|p|pp|para|subpara|pt|r|sec|subsec|sv|sch|tit|vrs|vol)\. *)/, STATUTE_SUBDIV_STRINGS: { "art.": "article", "bk.": "book", @@ -170,14 +147,9 @@ var CSL = { "juris-title-short": true, "juris-main": true, "juris-main-short": true, - "juris-comma-spotter": true, - "juris-default-spotter": true, - "juris-comma-spotter-short": true, - "juris-default-spotter-short": true, - "juris-locator": true, - "juris-locator-label": true, "juris-tail": true, - "juris-tail-short": true + "juris-tail-short": true, + "juris-locator": true }, MODULE_TYPES: { "legal_case": true, @@ -192,9 +164,35 @@ var CSL = { ["(", "["], [")", "]"] ], - checkNestedBraceOpen: new RegExp(".*\\("), - checkNestedBraceClose: new RegExp(".*\\)"), - MULTI_FIELDS: ["event", "publisher", "publisher-place", "event-place", "title", "container-title", "collection-title", "authority","edition","genre","title-short","medium","jurisdiction","archive","archive-place"], + checkNestedBrace: function(state) { + if (state.opt.xclass === "note") { + this.depth = 0; + this.update = function(str) { + var str = str ? str : ''; + var lst = str.split(/([\(\)])/); + for (var i=1,ilen=lst.length;i).*?(?:<\/span>|<\/?(?:i|sc|b)>)))/g); - lst = str.split(/(?:(?:\"|\')|(?:(?:).*?(?:<\/span>|<\/?(?:i|sc|b)>)))/g); - myret = [lst[0]]; - for (pos = 1, len = lst.length; pos < len; pos += 1) { - myret.push(mx[pos - 1]); - myret.push(lst[pos]); + if (!stopWords) { + stopWords = []; } - lst = myret.slice(); + var pairs = { + "": "", + "": "" + }; + var stack = []; + str = str.replace(/()/g, "$1 $2$3"); + var m1match = str.match(/((?: \"| \'|\" |\'[-.,;\?:]|\[|\]|\(|\)||<\/span>|<\/?(?:i|sc|b)>))/g); + if (!m1match) { + return [str]; + } + var m1split = str.split(/(?: \"| \'|\" |\'[-.,;\?:]|\[|\]|\(|\)||<\/span>|<\/?(?:i|sc|b)>)/g); + outer: for (var i=0,ilen=m1match.length; i -1) { + if (!m1split[i-1].match(/[:\?\!]\s*$/)) { + m1match[i-1] = m1match[i-1] + mFirstWord[1]; + m1split[i] = mFirstWord[3]; + } + } + } + continue; + } + if (stack.length) { + for (var j=stack.length-1; j>-1; j--) { + var stackObj = stack.slice(j)[0]; + if (m1match[i] === pairs[stackObj.tag]) { + stack = stack.slice(0, j+1); + var startPos = stack[j].pos; + for (var k=stack[j].pos+1; k -1 && !myjson.children[i].attrs.prefix && !myjson.children[i].attrs.suffix) { + mustHaves = mustHaves.slice(0,haveVarname).concat(mustHaves.slice(haveVarname+1)); + } else { + useme = false; + break; + } + } + if (useme && !mustHaves.length) { + myjson.attrs["has-publisher-and-publisher-place"] = true; + } + } + for (var i=0,ilen=myjson.children.length;i 0) { + var myparents = parents.slice(); + var parent = myparents.pop(); + if (parent === "substitute") { + return true; + } else { + return this.isChildOfSubstitute(myparents); + } + } + return false; +}; +CSL.XmlJSON.prototype.addMissingNameNodes = function(myjson,parents) { + if (!parents) { + parents = []; + } + if (myjson.name === "names") { + if (!this.isChildOfSubstitute(parents)) { + var addName = true; + for (var i=0,ilen=myjson.children.length;i -1) { + var institution = this.nodeCopy(this.institution); + for (var i=0,ilen = CSL.INSTITUTION_KEYS.length;i/, ""); + xml = xml.replace(//g, ""); + xml = xml.replace(/^\s+/g, ""); + xml = xml.replace(/\s+$/g, ""); + return xml; +}; +CSL.parseXml = function(str) { + var _pos = 0; + var _obj = {children:[]}; + var _stack = [_obj.children]; + function _listifyString(str) { + str = str.split("\n").join(" ").replace(/>[ ]+<").replace(/<\!--.*?-->/g, ""); + var lst = str.split("><"); + var stylePos = null; + for (var i=0,ilen=lst.length;i 0) { + lst[i] = "<" + lst[i]; + } + if (i < (lst.length-1)) { + lst[i] = lst[i] + ">"; + } + if ("number" != typeof stylePos) { + if (lst[i].slice(0, 7) === "