zotero/app/scripts/fetch_xulrunner
abaevbog 66fa9fdc51
do not trigger event causing autocomplete error (#3925)
DOMInputPasswordAdded event is triggered on autocomplete
submission which causes an error in LoginManager.
The error gets logged in the console, though the autocomplete does
work. This just removes the event from ActorManagerParent.

Fixes: #3883
2024-04-08 01:45:00 -04:00

549 lines
25 KiB
Bash
Executable file

#!/bin/bash
set -euo pipefail
# Copyright (c) 2011 Zotero
# Center for History and New Media
# George Mason University, Fairfax, Virginia, USA
# http://zotero.org
#
# This program is free software: you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation, either version 3 of the License, 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 General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program. If not, see <http://www.gnu.org/licenses/>.
SCRIPT_DIR="$( cd "$( dirname "${BASH_SOURCE[0]}" )" && pwd )"
APP_ROOT_DIR="$(dirname "$SCRIPT_DIR")"
. "$APP_ROOT_DIR/config.sh"
cd "$APP_ROOT_DIR"
function usage {
cat >&2 <<DONE
Usage: $0 -p platforms [-s]
Options
-p PLATFORMS Platforms to build (m=Mac, w=Windows, l=Linux)
DONE
exit 1
}
BUILD_MAC=0
BUILD_WIN=0
BUILD_LINUX=0
while getopts "p:s" opt; do
case $opt in
p)
for i in `seq 0 1 $((${#OPTARG}-1))`
do
case ${OPTARG:i:1} in
m) BUILD_MAC=1;;
w) BUILD_WIN=1;;
l) BUILD_LINUX=1;;
*)
echo "$0: Invalid platform option ${OPTARG:i:1}"
usage
;;
esac
done
;;
esac
shift $((OPTIND-1)); OPTIND=1
done
# Require at least one platform
if [[ $BUILD_MAC == 0 ]] && [[ $BUILD_WIN == 0 ]] && [[ $BUILD_LINUX == 0 ]]; then
usage
fi
function replace_line {
pattern=$1
replacement=$2
file=$3
if egrep -q "$pattern" "$file"; then
perl -pi -e "s/$pattern/$replacement/" "$file"
else
echo "$pattern" not found in "$file" -- aborting 2>&1
exit 1
fi
}
function remove_line {
pattern=$1
file=$2
if egrep -q "$pattern" "$file"; then
egrep -v "$pattern" "$file" > "$file.tmp"
mv "$file.tmp" "$file"
else
echo "$pattern" not found in "$file" -- aborting 2>&1
exit 1
fi
}
function get_utf16_chars {
str=$(echo -n "$1" | xxd -p | fold -w 2 | sed -r 's/(.+)/\\\\x{\1}\\\\x{00}/')
# Add NUL padding
if [ -n "${2:-}" ]; then
# Multiply characters x 2 for UTF-16
for i in `seq 1 $(($2 * 2))`; do
str+=$(echo '\\x{00}')
done
fi
echo $str | xargs | sed 's/ //g'
}
#
# Make various modifications to the stock Firefox app
#
function modify_omni {
platform=$1
mkdir omni
mv omni.ja omni
cd omni
# omni.ja is an "optimized" ZIP file, so use a script from Mozilla to avoid a warning from unzip
# here and to make it work after rezipping below
python3 "$APP_ROOT_DIR/scripts/optimizejars.py" --deoptimize ./ ./ ./
rm -f omni.ja.log
unzip omni.ja
rm omni.ja
replace_line 'BROWSER_CHROME_URL:.+' 'BROWSER_CHROME_URL: "chrome:\/\/zotero\/content\/zoteroPane.xhtml",' modules/AppConstants.sys.mjs
# https://firefox-source-docs.mozilla.org/toolkit/components/telemetry/internals/preferences.html
#
# It's not clear that most of these do anything anymore when not compiled in, but just in case
replace_line 'MOZ_REQUIRE_SIGNING:' 'MOZ_REQUIRE_SIGNING: false \&\&' modules/AppConstants.sys.mjs
replace_line 'MOZ_DATA_REPORTING:' 'MOZ_DATA_REPORTING: false \&\&' modules/AppConstants.sys.mjs
replace_line 'MOZ_SERVICES_HEALTHREPORT:' 'MOZ_SERVICES_HEALTHREPORT: false \&\&' modules/AppConstants.sys.mjs
replace_line 'MOZ_TELEMETRY_REPORTING:' 'MOZ_TELEMETRY_REPORTING: false \&\&' modules/AppConstants.sys.mjs
replace_line 'MOZ_TELEMETRY_ON_BY_DEFAULT:' 'MOZ_TELEMETRY_ON_BY_DEFAULT: false \&\&' modules/AppConstants.sys.mjs
replace_line 'MOZ_CRASHREPORTER:' 'MOZ_CRASHREPORTER: false \&\&' modules/AppConstants.sys.mjs
replace_line 'MOZ_UPDATE_CHANNEL:.+' 'MOZ_UPDATE_CHANNEL: "none",' modules/AppConstants.sys.mjs
replace_line '"https:\/\/[^\/]+mozilla.com.+"' '""' modules/AppConstants.sys.mjs
# Don't use Mozilla Maintenance Service on Windows
replace_line 'MOZ_MAINTENANCE_SERVICE:' 'MOZ_MAINTENANCE_SERVICE: false \&\&' modules/AppConstants.sys.mjs
# Continue using app.update.auto in prefs.js on Windows
replace_line 'PER_INSTALLATION_PREFS_PLATFORMS = \["win"\]' 'PER_INSTALLATION_PREFS_PLATFORMS = []' modules/UpdateUtils.sys.mjs
# Prompt if major update is available instead of installing automatically on restart
replace_line 'if \(!updateAuto\) \{' 'if (update.type == "major") {
LOG("UpdateService:_selectAndInstallUpdate - prompting because it is a major update");
AUSTLMY.pingCheckCode(this._pingSuffix, AUSTLMY.CHK_SHOWPROMPT_PREF);
Services.obs.notifyObservers(update, "update-available", "show-prompt");
return;
}
if (!updateAuto) {' modules/UpdateService.sys.mjs
# Avoid console warning about resource://gre/modules/FxAccountsCommon.js
replace_line 'const logins = this._data.logins;' 'const logins = this._data.logins; if (this._data.logins.length != -1) return;' modules/LoginStore.sys.mjs
# Prevent error during network requests
replace_line 'async lazyInit\(\) \{' 'async lazyInit() { if (this.features) return false;' modules/UrlClassifierExceptionListService.sys.mjs
replace_line 'pref\("network.captive-portal-service.enabled".+' 'pref("network.captive-portal-service.enabled", false);' greprefs.js
replace_line 'pref\("network.connectivity-service.enabled".+' 'pref("network.connectivity-service.enabled", false);' greprefs.js
replace_line 'pref\("toolkit.telemetry.server".+' 'pref("toolkit.telemetry.server", "");' greprefs.js
replace_line 'pref\("toolkit.telemetry.unified".+' 'pref("toolkit.telemetry.unified", false);' greprefs.js
replace_line 'pref\("media.gmp-manager.url".+' 'pref("media.gmp-manager.url", "");' greprefs.js
#
# # Disable transaction timeout
# perl -pi -e 's/let timeoutPromise/\/*let timeoutPromise/' modules/Sqlite.jsm
# perl -pi -e 's/return Promise.race\(\[transactionPromise, timeoutPromise\]\);/*\/return transactionPromise;/' modules/Sqlite.jsm
# rm -f jsloader/resource/gre/modules/Sqlite.jsm
#
# Disable unwanted components
remove_line '(RemoteSettings|services-|telemetry|Telemetry|URLDecorationAnnotationsService)' components/components.manifest
# Do not trigger LoginManager event that logs an error on autocomplete submission
remove_line 'DOMInputPasswordAdded: \{\},' modules/ActorManagerParent.sys.mjs
# On Mac/Linux, ignore relative paths in PATH in Subprocess.pathSearch(), used when a bare command is passed to Utilities.Internal.subprocess()
if [[ $platform != win* ]]; then
replace_line 'let path = PathUtils.join\(dir, bin\);' 'if (!dir.startsWith("\/")) continue; let path = PathUtils.join(dir, bin);' modules/subprocess/subprocess_unix.sys.mjs
fi
# Remove unwanted files
rm modules/FxAccounts*
# Causes a startup error -- try an empty file or a shim instead?
#rm modules/Telemetry*
rm modules/URLDecorationAnnotationsService.sys.mjs
rm -rf modules/services-*
# Clear most WebExtension manifest properties
replace_line 'manifest = normalized.value;' 'manifest = normalized.value;
if (this.type == "extension") {
if (!manifest.applications?.zotero?.id) {
this.manifestError("applications.zotero.id not provided");
}
if (!manifest.applications?.zotero?.update_url) {
this.manifestError("applications.zotero.update_url not provided");
}
if (!manifest.applications?.zotero?.strict_max_version) {
this.manifestError("applications.zotero.strict_max_version not provided");
}
manifest.browser_specific_settings = undefined;
manifest.content_scripts = [];
manifest.permissions = [];
manifest.host_permissions = [];
manifest.web_accessible_resources = undefined;
manifest.experiment_apis = {};
}' modules/Extension.sys.mjs
# Use applications.zotero instead of applications.gecko
replace_line 'let bss = manifest.applications\?.gecko' 'let bss = manifest.applications?.zotero' modules/addons/XPIInstall.jsm
replace_line 'manifest.applications\?.gecko' 'manifest.applications?.zotero' modules/Extension.sys.mjs
# When installing addon, use app version instead of toolkit version for targetApplication
replace_line "id: TOOLKIT_ID," "id: '$APP_ID'," modules/addons/XPIInstall.jsm
# Accept zotero@chnm.gmu.edu for target application to allow Zotero 6 plugins to remain
# installed in Zotero 7
replace_line "if \(targetApp.id == Services.appinfo.ID\) \{" "if (targetApp.id == 'zotero\@chnm.gmu.edu') targetApp.id = '$APP_ID'; if (targetApp.id == Services.appinfo.ID) {" modules/addons/XPIDatabase.jsm
# Fix addon.id is undefined with built-in theme addons, anyway we don't support theme addons
replace_line 'addon.type === "theme"' 'false' modules/addons/XPIDatabase.jsm
# For updates, look for applications.zotero instead of applications.gecko in manifest.json and
# use the app id and version for strict_min_version/strict_max_version comparisons
replace_line 'gecko: \{\},' 'zotero: {},' modules/addons/AddonUpdateChecker.sys.mjs
replace_line 'if \(!\("gecko" in applications\)\) \{' 'if (!("zotero" in applications)) {' modules/addons/AddonUpdateChecker.sys.mjs
replace_line '"gecko not in application entry' '"zotero not in application entry' modules/addons/AddonUpdateChecker.sys.mjs
replace_line 'let app = getProperty\(applications, "gecko", "object"\);' 'let app = getProperty(applications, "zotero", "object");' modules/addons/AddonUpdateChecker.sys.mjs
replace_line "id: TOOLKIT_ID," "id: '$APP_ID'," modules/addons/AddonUpdateChecker.sys.mjs
replace_line 'lazy.AddonManagerPrivate.webExtensionsMinPlatformVersion' '"7.0"' modules/addons/AddonUpdateChecker.sys.mjs
replace_line 'result.targetApplications.push' 'false && result.targetApplications.push' modules/addons/AddonUpdateChecker.sys.mjs
# Allow addon installation by bypassing confirmation dialogs. If we want a confirmation dialog,
# we need to either add gXPInstallObserver from browser-addons.js [1][2] or provide our own with
# Ci.amIWebInstallPrompt [3].
#
# [1] https://searchfox.org/mozilla-esr102/rev/5a6d529652045050c5cdedc0558238949b113741/browser/base/content/browser.js#1902-1923
# [2] https://searchfox.org/mozilla-esr102/rev/5a6d529652045050c5cdedc0558238949b113741/browser/base/content/browser-addons.js#201
# [3] https://searchfox.org/mozilla-esr102/rev/5a6d529652045050c5cdedc0558238949b113741/toolkit/mozapps/extensions/AddonManager.sys.mjs#3114-3124
replace_line 'if \(info.addon.userPermissions\) \{' 'if (false) {' modules/AddonManager.sys.mjs
replace_line '\} else if \(info.addon.sitePermissions\) \{' '} else if (false) {' modules/AddonManager.sys.mjs
replace_line '\} else if \(requireConfirm\) \{' '} else if (false) {' modules/AddonManager.sys.mjs
# Make addon listener methods wait for promises, to allow calling asynchronous plugin `shutdown`
# and `uninstall` methods in our `onInstalling` handler
replace_line 'callAddonListeners\(aMethod' 'async callAddonListeners(aMethod' modules/AddonManager.sys.mjs
# Don't need this one to be async, but we can't easily avoid modifying its `listener[aMethod].apply()` call
replace_line 'callManagerListeners\(aMethod' 'async callManagerListeners(aMethod' modules/AddonManager.sys.mjs
replace_line 'AddonManagerInternal.callAddonListeners.apply\(AddonManagerInternal, aArgs\);' \
'return AddonManagerInternal.callAddonListeners.apply(AddonManagerInternal, aArgs);' modules/AddonManager.sys.mjs
replace_line 'listener\[aMethod\].apply\(listener, aArgs\);' \
'let maybePromise = listener[aMethod].apply(listener, aArgs);
if (maybePromise && maybePromise.then) await maybePromise;' modules/AddonManager.sys.mjs
replace_line 'AddonManagerPrivate.callAddonListeners' 'await AddonManagerPrivate.callAddonListeners' modules/addons/XPIInstall.jsm
replace_line 'let uninstall = \(\) => \{' 'let uninstall = async () => {' modules/addons/XPIInstall.jsm
replace_line 'cancelUninstallAddon\(aAddon\)' 'async cancelUninstallAddon(aAddon)' modules/addons/XPIInstall.jsm
# No idea why this is necessary, but without it initialization fails with "TypeError: "constructor" is read-only"
replace_line 'LoginStore.prototype.constructor = LoginStore;' '\/\/LoginStore.prototype.constructor = LoginStore;' modules/LoginStore.sys.mjs
#
# # Allow proxy password saving
# perl -pi -e 's/get _inPrivateBrowsing\(\) \{/get _inPrivateBrowsing() {if (true) { return false; }/' components/nsLoginManagerPrompter.js
#
# # Change text in update dialog
# perl -pi -e 's/A security and stability update for/A new version of/' chrome/en-US/locale/en-US/mozapps/update/updates.properties
# perl -pi -e 's/updateType_major=New Version/updateType_major=New Major Version/' chrome/en-US/locale/en-US/mozapps/update/updates.properties
# perl -pi -e 's/updateType_minor=Security Update/updateType_minor=New Version/' chrome/en-US/locale/en-US/mozapps/update/updates.properties
# perl -pi -e 's/update for &brandShortName; as soon as possible/update as soon as possible/' chrome/en-US/locale/en-US/mozapps/update/updates.dtd
#
# Set available locales
cp "$APP_ROOT_DIR/assets/multilocale.txt" res/multilocale.txt
# Use Zotero URL opening in Mozilla dialogs (e.g., app update dialog)
replace_line 'function openURL\(aURL\) \{' 'function openURL(aURL) {let {Zotero} = ChromeUtils.importESModule("chrome:\/\/zotero\/content\/zotero.mjs"); Zotero.launchURL(aURL); if (true) { return; }' chrome/toolkit/content/global/contentAreaUtils.js
#
# Modify Add-ons window
#
# Prevent display: block from overriding display: none on <hr>s
replace_line 'display: block !important;' 'display: block;' chrome/toolkit/content/global/elements/panel-list.css
file="chrome/toolkit/content/mozapps/extensions/aboutaddons.css"
echo >> $file
# Hide search bar, Themes and Plugins tabs, and sidebar footer
echo '.main-search, button[name="theme"], button[name="plugin"], sidebar-footer { display: none; }' >> $file
echo '.main-heading { margin-top: 2em; }' >> $file
# Hide Details/Permissions tabs in addon details so we only show details
echo 'addon-details > button-group { display: none !important; }' >> $file
# Hide "Debug Addons" and "Manage Extension Shortcuts"
echo 'panel-item[action="debug-addons"], panel-item[action="reset-update-states"] + hr, panel-item[action="manage-shortcuts"] { display: none }' >> $file
# Show cursor feedback on plugin homepage links
echo '.addon-detail-row-homepage .text-link { cursor: pointer; color: -moz-nativehyperlinktext; }' >> $file
echo '.addon-detail-row-homepage .text-link:hover { text-decoration: underline; }' >> $file
file="chrome/toolkit/content/mozapps/extensions/aboutaddons.js"
# Hide unsigned-addon warning
replace_line 'if \(!isCorrectlySigned\(addon\)\) \{' 'if (!isCorrectlySigned(addon)) {return {};' $file
# Hide Private Browsing setting in addon details
replace_line 'pbRow\.' '\/\/pbRow.' $file
replace_line 'let isAllowed = await isAllowedInPrivateBrowsing' '\/\/let isAllowed = await isAllowedInPrivateBrowsing' $file
# Use our own strings for the removal prompt
replace_line 'let \{ BrowserAddonUI \} = windowRoot.ownerGlobal;' '' $file
replace_line 'await BrowserAddonUI.promptRemoveExtension' 'promptRemoveExtension' $file
# Customize empty-list message
replace_line 'createEmptyListMessage\(\) {' 'createEmptyListMessage() {
var p = document.createElement("p");
p.id = "empty-list-message";
return p;' $file
# Swap in include.js, which we need for Zotero.getString(), for abuse-reports.js, which we don't need
# Open plugin links in external browser
replace_line 'let homepageURL = homepageRow.querySelector\(\"a\"\);' 'let homepageURL = homepageRow.querySelector(\"\.text-link\");' $file
replace_line 'homepageURL.href = addon.homepageURL;' 'homepageURL.setAttribute("href", addon.homepageURL);' $file
replace_line '<a target="_blank" dir="ltr"><\/a>' \
'<label target="_blank" class="text-link" dir="ltr"><\/label>' \
chrome/toolkit/content/mozapps/extensions/aboutaddons.html
# Hide Recommendations tab in sidebar and recommendations in main pane
replace_line 'function isDiscoverEnabled\(\) \{' 'function isDiscoverEnabled() {return false;' chrome/toolkit/content/mozapps/extensions/aboutaddonsCommon.js
replace_line 'pref\("extensions.htmlaboutaddons.recommendations.enabled".+' 'pref("extensions.htmlaboutaddons.recommendations.enabled", false);' greprefs.js
# Hide Report option
replace_line 'pref\("extensions.abuseReport.enabled".+' 'pref("extensions.abuseReport.enabled", false);' greprefs.js
# The first displayed Services.prompt dialog's size jumps around because sizeToContent() is called twice
# Fix by preventing the first sizeToContent() call if the icon hasn't been loaded yet
replace_line 'window.sizeToContent\(\);' 'if (ui.infoIcon.complete) window.sizeToContent();' chrome/toolkit/content/global/commonDialog.js
replace_line 'ui.infoIcon.addEventListener' 'if (!ui.infoIcon.complete) ui.infoIcon.addEventListener' chrome/toolkit/content/global/commonDialog.js
# Import style into built-in dialogs
replace_line 'id=\"commonDialogWindow\"' \
'id=\"commonDialogWindow\" class=\"zotero-dialog\"' \
chrome/toolkit/content/global/commonDialog.xhtml
replace_line '<\?xml-stylesheet href=\"chrome:\/\/global\/skin\/commonDialog.css\" type=\"text\/css\"\?>' \
'<\?xml-stylesheet href=\"chrome:\/\/global\/skin\/commonDialog.css\" type=\"text\/css\"\?>
<\?xml-stylesheet href=\"chrome:\/\/zotero-platform\/content\/zotero.css\" type=\"text\/css\"\?>' \
chrome/toolkit/content/global/commonDialog.xhtml
# commonDialog.xhtml can be opened via Services.prompt in the Profile Manager, so check for a profile first
replace_line '<script>' \
'<script>
try {
Services.dirsvc.get(\"ProfD\", Ci.nsIFile);
Services.scriptloader.loadSubScript(\"chrome:\/\/zotero\/content\/include.js\", this);
Services.scriptloader.loadSubScript(\"chrome:\/\/zotero\/content\/customElements.js\", this);
} catch (e) {}' \
chrome/toolkit/content/global/commonDialog.xhtml
# Use native checkbox instead of Firefox-themed version in prompt dialogs
replace_line '<xul:checkbox' '<xul:checkbox native=\"true\"' chrome/toolkit/content/global/commonDialog.xhtml
# The <browser> CE appends its autoscroll <popup> to document.documentElement, which doesn't work in zoteroPane.xhtml
# (in Firefox browser.xhtml, document.documentElement is <html>, which can contain <popup>s; in zoteroPane.xhtml, it's
# <window>, which can't)
# Fix by appending it to a <popupset> instead
replace_line 'document.documentElement.appendChild\(this._autoScrollPopup\);' 'let popupset = document.querySelector("popupset");
if (!popupset) {
popupset = document.createXULElement("popupset");
document.documentElement.appendChild(popupset);
}
popupset.appendChild(this._autoScrollPopup);' chrome/toolkit/content/global/elements/browser-custom-element.js
zip -qr9XD omni.ja *
mv omni.ja ..
cd ..
python3 "$APP_ROOT_DIR/scripts/optimizejars.py" --optimize ./ ./ ./
rm -rf omni
# Unzip browser/omni.ja and leave unzipped
cd browser
mkdir omni
mv omni.ja omni
cd omni
ls -la
set +e
unzip omni.ja
set -e
rm omni.ja
# Remove Firefox update URLs
remove_line 'pref\("app.update.url.(manual|details)' defaults/preferences/firefox-branding.js
# Remove Firefox overrides (e.g., to use Firefox-specific strings for connection errors)
remove_line '(override)' chrome/chrome.manifest
# Remove WebExtension APIs
remove_line ext-browser.json components/components.manifest
# Don't open a second window if app is already open when launching .exe (Windows) or running via
# command line (macOS)
replace_line 'function dch_handle\(cmdLine\) \{' 'function dch_handle(cmdLine) {
if (cmdLine.state == Ci.nsICommandLine.STATE_REMOTE_AUTO) { return; }
' modules/BrowserContentHandler.sys.mjs
}
mkdir -p xulrunner
cd xulrunner
if [ $BUILD_MAC == 1 ]; then
GECKO_VERSION="$GECKO_VERSION_MAC"
DOWNLOAD_URL="https://ftp.mozilla.org/pub/firefox/releases/$GECKO_VERSION"
rm -rf Firefox.app
if [ -e "Firefox $GECKO_VERSION.app.zip" ]; then
echo "Using Firefox $GECKO_VERSION.app.zip"
unzip "Firefox $GECKO_VERSION.app.zip"
else
curl -o Firefox.dmg "$DOWNLOAD_URL/mac/en-US/Firefox%20$GECKO_VERSION.dmg"
set +e
hdiutil detach -quiet /Volumes/Firefox 2>/dev/null
set -e
hdiutil attach -quiet Firefox.dmg
cp -a /Volumes/Firefox/Firefox.app .
hdiutil detach -quiet /Volumes/Firefox
fi
# Download custom components
#echo
#rm -rf MacOS
#if [ -e "Firefox $GECKO_VERSION MacOS.zip" ]; then
# echo "Using Firefox $GECKO_VERSION MacOS.zip"
# unzip "Firefox $GECKO_VERSION MacOS.zip"
#else
# echo "Downloading Firefox $GECKO_VERSION MacOS.zip"
# curl -o MacOS.zip "${custom_components_url}Firefox%20$GECKO_VERSION%20MacOS.zip"
# unzip MacOS.zip
#fi
#echo
pushd Firefox.app/Contents/Resources
modify_omni mac
popd
# Replace "FirefoxCP" with "ZoteroCP" for subprocesses ("Isolated Web Content", "Socket Process", "Web Content", etc.)
info_plist=Firefox.app/Contents/MacOS/plugin-container.app/Contents/Resources/English.lproj/InfoPlist.strings
from=$(get_utf16_chars "FirefoxCP")
to=$(get_utf16_chars "ZoteroCP")
perl -pi -e "s/$from/$to/" $info_plist
# Check for UTF-16 "ZoteroCP"
if ! grep -a -q "Z.o.t.e.r.o.C.P." $info_plist; then
echo '"ZoteroCP" not found in InfoPlist.strings after replacement'
exit 1
fi
if [ ! -e "Firefox $GECKO_VERSION.app.zip" ]; then
rm "Firefox.dmg"
fi
#if [ ! -e "Firefox $GECKO_VERSION MacOS.zip" ]; then
# rm "MacOS.zip"
#fi
echo $("$SCRIPT_DIR/xulrunner_hash" -p m) > hash-mac
fi
if [ $BUILD_WIN == 1 ]; then
GECKO_VERSION="$GECKO_VERSION_WIN"
DOWNLOAD_URL="https://ftp.mozilla.org/pub/firefox/releases/$GECKO_VERSION"
for arch in win32 win-x64 win-aarch64; do
xdir=firefox-$arch
rm -rf $xdir
mkdir $xdir
if [ -e "Firefox Setup $GECKO_VERSION-$arch.exe" ]; then
echo "Using Firefox Setup $GECKO_VERSION-$arch.exe"
cp "Firefox Setup $GECKO_VERSION-$arch.exe" "Firefox%20Setup%20$GECKO_VERSION.exe"
else
if [ $arch = "win-x64" ]; then
curl -O "$DOWNLOAD_URL/win64/en-US/Firefox%20Setup%20$GECKO_VERSION.exe"
elif [ $arch = "win-aarch64" ]; then
curl -O "$DOWNLOAD_URL/win64-aarch64/en-US/Firefox%20Setup%20$GECKO_VERSION.exe"
else
curl -O "$DOWNLOAD_URL/$arch/en-US/Firefox%20Setup%20$GECKO_VERSION.exe"
fi
fi
7z x Firefox%20Setup%20$GECKO_VERSION.exe -o$xdir 'core/*'
mv $xdir/core $xdir-core
rm -rf $xdir
mv $xdir-core $xdir
pushd $xdir
# Replace "Mozilla-1de4eec8-1241-4177-a864-e594e8d1fb38" with "Zotero" for C:\ProgramData directory
#
# Mozilla uses a UUID in the path because they previously used just "Mozilla" and needed to
# recreate the folder with correct permissions for security reasons, but we never had a folder in
# ProgramData, so we can just create it as "Zotero". Instead of using a custom xul.dll, just
# replace the hard-coded string with "Zotero" and add a bunch of NULs.
from=$(get_utf16_chars "Mozilla-1de4eec8-1241-4177-a864-e594e8d1fb38")
to=$(get_utf16_chars "Zotero" 38)
perl -pe "s/$from/$to/" < xul.dll > xul.dll.new
mv xul.dll.new xul.dll
# Check for UTF-16 "Zotero" in DLL
#
# (The macOS strings command doesn't have an encoding option, so skip on macOS. We could
# require binutils, which has GNU strings, but you need to build on Windows to make an
# installer, so a Windows build from macOS likely isn't being deployed, and there's no
# reason the Perl command above should fail anyway.)
if [[ "`uname`" != "Darwin" ]] && [[ -z "$(strings -e l xul.dll | grep -m 1 Zotero)" ]]; then
echo '"Zotero" not found in xul.dll after replacement'
exit 1
fi
modify_omni $arch
# Disable skeleton UI window
# https://forums.zotero.org/discussion/comment/437636/#Comment_437636
replace_line 'pref\("browser\.startup\.preXulSkeletonUI", true\);' 'pref("browser.startup.preXulSkeletonUI", false);' defaults/preferences/firefox.js
popd
# Uncomment to create local copies for reuse
#cp "Firefox%20Setup%20$GECKO_VERSION.exe" "Firefox Setup $GECKO_VERSION-$arch.exe"
rm "Firefox%20Setup%20$GECKO_VERSION.exe"
echo
echo
done
echo $("$SCRIPT_DIR/xulrunner_hash" -p w) > hash-win
fi
if [ $BUILD_LINUX == 1 ]; then
GECKO_VERSION="$GECKO_VERSION_LINUX"
DOWNLOAD_URL="https://ftp.mozilla.org/pub/firefox/releases/$GECKO_VERSION"
# Include 32-bit build if not in CI
if [[ "${CI:-}" = "1" ]] || [[ "${SKIP_32:-}" = "1" ]]; then
arches="x86_64"
else
arches="i686 x86_64"
fi
for arch in $arches; do
xdir="firefox-$arch"
rm -rf $xdir
archived_file="firefox-$GECKO_VERSION-$arch.tar.bz2"
if [ -e "$archived_file" ]; then
echo "Using $archived_file"
cp "$archived_file" "firefox-$GECKO_VERSION.tar.bz2"
else
curl -O "$DOWNLOAD_URL/linux-$arch/en-US/firefox-$GECKO_VERSION.tar.bz2"
fi
tar xvf firefox-$GECKO_VERSION.tar.bz2
mv firefox firefox-$arch
pushd firefox-$arch
modify_omni $arch
popd
echo $($SCRIPT_DIR/xulrunner_hash -p l) > hash-linux
rm "firefox-$GECKO_VERSION.tar.bz2"
done
fi
echo Done