mirror of
https://github.com/freedomofpress/dangerzone.git
synced 2025-04-29 02:12:36 +02:00

Work around the issue by adding some extra functionality to the "Next" button on the welcome screen of the installer. When the user clicks it to proceed with the installation this: 1. Flips the install scope to "perUser" which is the default in WiX 3 2. Finds the older installation 3. And finally flips the scope back to "perMachine" which is the default in WiX 4 and newer TODO: Revert this once we are reasonably certain there are no affected Dangerzone Installations?
284 lines
8.5 KiB
Python
284 lines
8.5 KiB
Python
#!/usr/bin/env python3
|
|
import os
|
|
import uuid
|
|
import xml.etree.ElementTree as ET
|
|
|
|
|
|
def build_data(base_path, path_prefix, dir_id, dir_name):
|
|
data = {
|
|
"directory_name": dir_name,
|
|
"directory_id": dir_id,
|
|
"files": [],
|
|
"dirs": [],
|
|
}
|
|
|
|
if dir_id == "INSTALLFOLDER":
|
|
data["component_id"] = "ApplicationFiles"
|
|
else:
|
|
data["component_id"] = "Component" + dir_id
|
|
data["component_guid"] = str(uuid.uuid4()).upper()
|
|
|
|
for entry in os.listdir(base_path):
|
|
entry_path = os.path.join(base_path, entry)
|
|
if os.path.isfile(entry_path):
|
|
data["files"].append(os.path.join(path_prefix, entry))
|
|
elif os.path.isdir(entry_path):
|
|
if dir_id == "INSTALLFOLDER":
|
|
next_dir_prefix = "Folder"
|
|
else:
|
|
next_dir_prefix = dir_id
|
|
|
|
# Skip lib/PySide6/examples folder due to ilegal file names
|
|
if "\\build\\exe.win-amd64-3.12\\lib\\PySide6\\examples" in base_path:
|
|
continue
|
|
|
|
# Skip lib/PySide6/qml/QtQuick folder due to ilegal file names
|
|
# XXX Since we're not using Qml it should be no problem
|
|
if "\\build\\exe.win-amd64-3.12\\lib\\PySide6\\qml\\QtQuick" in base_path:
|
|
continue
|
|
|
|
next_dir_id = next_dir_prefix + entry.capitalize().replace("-", "_")
|
|
subdata = build_data(
|
|
os.path.join(base_path, entry),
|
|
os.path.join(path_prefix, entry),
|
|
next_dir_id,
|
|
entry,
|
|
)
|
|
|
|
# Add the subdirectory only if it contains files or subdirectories
|
|
if subdata["files"] or subdata["dirs"]:
|
|
data["dirs"].append(subdata)
|
|
|
|
return data
|
|
|
|
|
|
def build_directory_xml(root, data):
|
|
attrs = {}
|
|
attrs["Id"] = data["directory_id"]
|
|
attrs["Name"] = data["directory_name"]
|
|
directory_el = ET.SubElement(root, "Directory", attrs)
|
|
for subdata in data["dirs"]:
|
|
build_directory_xml(directory_el, subdata)
|
|
|
|
|
|
def build_components_xml(root, data):
|
|
component_el = ET.SubElement(
|
|
root,
|
|
"Component",
|
|
Id=data["component_id"],
|
|
Guid=data["component_guid"],
|
|
Directory=data["directory_id"],
|
|
)
|
|
for filename in data["files"]:
|
|
ET.SubElement(component_el, "File", Source=filename)
|
|
for subdata in data["dirs"]:
|
|
build_components_xml(root, subdata)
|
|
|
|
|
|
def main():
|
|
version_filename = os.path.join(
|
|
os.path.dirname(os.path.dirname(os.path.dirname(os.path.abspath(__file__)))),
|
|
"share",
|
|
"version.txt",
|
|
)
|
|
with open(version_filename) as f:
|
|
# Read the Dangerzone version from share/version.txt, and remove any potential
|
|
# -rc markers.
|
|
dangerzone_version = f.read().strip().split("-")[0]
|
|
|
|
dangerzone_product_upgrade_code = "12B9695C-965B-4BE0-BC33-21274E809576"
|
|
|
|
build_dir = os.path.join(
|
|
os.path.dirname(os.path.dirname(os.path.dirname(os.path.abspath(__file__)))),
|
|
"build",
|
|
)
|
|
|
|
cx_freeze_dir = "exe.win-amd64-3.12"
|
|
|
|
dist_dir = os.path.join(build_dir, cx_freeze_dir)
|
|
|
|
if not os.path.exists(dist_dir):
|
|
print("You must build the dangerzone binary before running this")
|
|
return
|
|
|
|
# Prepare data for WiX file harvesting from the output of cx_Freeze
|
|
data = build_data(
|
|
dist_dir,
|
|
cx_freeze_dir,
|
|
"INSTALLFOLDER",
|
|
"Dangerzone",
|
|
)
|
|
|
|
# Add the Wix root element
|
|
wix_el = ET.Element(
|
|
"Wix",
|
|
{
|
|
"xmlns": "http://wixtoolset.org/schemas/v4/wxs",
|
|
"xmlns:ui": "http://wixtoolset.org/schemas/v4/wxs/ui",
|
|
},
|
|
)
|
|
|
|
# Add the Package element
|
|
package_el = ET.SubElement(
|
|
wix_el,
|
|
"Package",
|
|
Name="Dangerzone",
|
|
Manufacturer="Freedom of the Press Foundation",
|
|
UpgradeCode=dangerzone_product_upgrade_code,
|
|
Language="1033",
|
|
Compressed="yes",
|
|
Codepage="1252",
|
|
Version=dangerzone_version,
|
|
)
|
|
|
|
ET.SubElement(
|
|
package_el,
|
|
"SummaryInformation",
|
|
Keywords="Installer",
|
|
Description="Dangerzone " + dangerzone_version + " Installer",
|
|
Codepage="1252",
|
|
)
|
|
ET.SubElement(package_el, "MediaTemplate", EmbedCab="yes")
|
|
ET.SubElement(
|
|
package_el, "Icon", Id="ProductIcon", SourceFile="..\\share\\dangerzone.ico"
|
|
)
|
|
ET.SubElement(package_el, "Property", Id="ARPPRODUCTICON", Value="ProductIcon")
|
|
ET.SubElement(
|
|
package_el,
|
|
"Property",
|
|
Id="ARPHELPLINK",
|
|
Value="https://dangerzone.rocks",
|
|
)
|
|
ET.SubElement(
|
|
package_el,
|
|
"Property",
|
|
Id="ARPURLINFOABOUT",
|
|
Value="https://freedom.press",
|
|
)
|
|
|
|
ui_el = ET.SubElement(package_el, "UI")
|
|
|
|
ET.SubElement(
|
|
ui_el, "ui:WixUI", Id="WixUI_InstallDir", InstallDirectory="INSTALLFOLDER"
|
|
)
|
|
ET.SubElement(ui_el, "UIRef", Id="WixUI_ErrorProgressText")
|
|
|
|
# Workaround for an issue after upgrading from WiX Toolset 3 to 5 where the older
|
|
# version of Dangerzone is not uninstalled during the upgrade
|
|
#
|
|
# Work around the issue by adding some extra functionality to the "Next" button on the welcome screen
|
|
# of the installer. When the user clicks it to proceed with the installation this:
|
|
# 1. Flips the install scope to "perUser" which is the default in WiX 3
|
|
# 2. Finds the older installation
|
|
# 3. And finally flips the scope back to "perMachine" which is the default in WiX 4 and newer
|
|
#
|
|
# Adapted from this stack overflow answer: https://stackoverflow.com/a/35064434
|
|
#
|
|
# TODO: Revert this once we are reasonably certain there are no affected Dangerzone Installations?
|
|
ET.SubElement(
|
|
ui_el,
|
|
"Publish",
|
|
Dialog="WelcomeDlg",
|
|
Control="Next",
|
|
Property="ALLUSERS",
|
|
Value="{}",
|
|
)
|
|
ET.SubElement(
|
|
ui_el,
|
|
"Publish",
|
|
Dialog="WelcomeDlg",
|
|
Control="Next",
|
|
Event="DoAction",
|
|
Value="FindRelatedProducts",
|
|
)
|
|
ET.SubElement(
|
|
ui_el,
|
|
"Publish",
|
|
Dialog="WelcomeDlg",
|
|
Control="Next",
|
|
Property="ALLUSERS",
|
|
Value="1",
|
|
)
|
|
|
|
ET.SubElement(
|
|
package_el,
|
|
"WixVariable",
|
|
Id="WixUILicenseRtf",
|
|
Value="..\\install\\windows\\license.rtf",
|
|
)
|
|
ET.SubElement(
|
|
package_el,
|
|
"WixVariable",
|
|
Id="WixUIDialogBmp",
|
|
Value="..\\install\\windows\\dialog.bmp",
|
|
)
|
|
ET.SubElement(
|
|
package_el,
|
|
"MajorUpgrade",
|
|
AllowSameVersionUpgrades="yes",
|
|
DowngradeErrorMessage="A newer version of [ProductName] is already installed. If you are sure you want to downgrade, remove the existing installation via Programs and Features.",
|
|
)
|
|
|
|
# Add the ProgramMenuFolder StandardDirectory
|
|
programmenufolder_el = ET.SubElement(
|
|
package_el,
|
|
"StandardDirectory",
|
|
Id="ProgramMenuFolder",
|
|
)
|
|
|
|
shortcut_el = ET.SubElement(
|
|
programmenufolder_el,
|
|
"Component",
|
|
Id="ApplicationShortcuts",
|
|
Guid="539E7DE8-A124-4C09-AA55-0DD516AAD7BC",
|
|
)
|
|
ET.SubElement(
|
|
shortcut_el,
|
|
"Shortcut",
|
|
Id="DangerzoneStartMenuShortcut",
|
|
Name="Dangerzone",
|
|
Description="Dangerzone",
|
|
Target="[INSTALLFOLDER]dangerzone.exe",
|
|
WorkingDirectory="INSTALLFOLDER",
|
|
)
|
|
ET.SubElement(
|
|
shortcut_el,
|
|
"RegistryValue",
|
|
Root="HKCU",
|
|
Key="Software\\Freedom of the Press Foundation\\Dangerzone",
|
|
Name="installed",
|
|
Type="integer",
|
|
Value="1",
|
|
KeyPath="yes",
|
|
)
|
|
|
|
# Add the ProgramFilesFolder StandardDirectory
|
|
programfilesfolder_el = ET.SubElement(
|
|
package_el,
|
|
"StandardDirectory",
|
|
Id="ProgramFiles64Folder",
|
|
)
|
|
|
|
# Generate the directory layout for the installed product
|
|
build_directory_xml(programfilesfolder_el, data)
|
|
|
|
applicationcomponents_el = ET.SubElement(
|
|
package_el, "ComponentGroup", Id="ApplicationComponents"
|
|
)
|
|
|
|
# Generate the components for the installed product
|
|
build_components_xml(applicationcomponents_el, data)
|
|
|
|
# Add the Feature element
|
|
feature_el = ET.SubElement(package_el, "Feature", Id="DefaultFeature", Level="1")
|
|
ET.SubElement(feature_el, "ComponentGroupRef", Id="ApplicationComponents")
|
|
ET.SubElement(feature_el, "ComponentRef", Id="ApplicationShortcuts")
|
|
|
|
ET.indent(wix_el, space=" ")
|
|
|
|
with open(os.path.join(build_dir, "Dangerzone.wxs"), "w") as wxs_file:
|
|
wxs_file.write(ET.tostring(wix_el).decode())
|
|
|
|
|
|
if __name__ == "__main__":
|
|
main()
|