tis-firefox-multi icon

Mozilla Firefox Multi-Language

Paquet d’installation silencieuse pour Mozilla Firefox Multi-Language

140.0-23

package           : tis-firefox-multi
version           : 140.0-23
architecture      : x86
section           : base
priority          : optional
name              : Mozilla Firefox Multi-Language
categories        : Internet
maintainer        : WAPT Team, Tranquil IT, Jimmy PELÉ, Amel FRADJ
description       : Mozilla Firefox, is a free and open-source web browser - The package is multi-language and pre-configured
depends           : 
conflicts         : tis-firefox, tis-firefox-esr, tis-firefox-esr-multi, tis-config-for-firefox, tis-config-firefox
maturity          : PROD
locale            : all
target_os         : windows
min_wapt_version  : 2.3
sources           : https://www.mozilla.org/firefox/all/#product-desktop-release
installed_size    : 220643328
impacted_process  : firefox
description_fr    : Mozilla Firefox, est un navigateur web gratuit et open source - Le paquet est multilingue et préconfiguré
description_pl    : Mozilla Firefox, jest darmową i otwartą przeglądarką internetową - Pakiet jest wielojęzyczny i wstępnie skonfigurowany
description_de    : Mozilla Firefox, ist ein kostenloser und quelloffener Webbrowser - Das Paket ist mehrsprachig und vorkonfiguriert
description_es    : Mozilla Firefox, es un navegador web gratuito y de código abierto - El paquete es multilingüe y está preconfigurado
description_pt    : Mozilla Firefox, é um navegador web gratuito e de código aberto - O pacote é multilingue e pré-configurado
description_it    : Mozilla Firefox è un browser web gratuito e open-source - Il pacchetto è multilingue e preconfigurato
description_nl    : Mozilla Firefox, is een gratis en open-source webbrowser - Het pakket is meertalig en voorgeconfigureerd
description_ru    : Mozilla Firefox - это бесплатный веб-браузер с открытым исходным кодом - Пакет является многоязычным и предварительно настроенным
audit_schedule    : 
editor            : Mozilla Foundation,Mozilla Corporation
keywords          : web,browser,navigateur,firefox,mozilla
licence           : MPL 2.0
homepage          : https://www.mozilla.org/
package_uuid      : 9e5f4927-f8d2-45b5-963d-6fbbe1621f41
valid_from        : 
valid_until       : 
forced_install_on : 
changelog         : https://www.mozilla.org/firefox/releases/
min_os_version    : 10.0
max_os_version    : 
icon_sha256sum    : 2dc82eade364831757e067169d0039e6e0c9b693f343ea9a62db709eb1942c9e
signer            : Tranquil IT
signer_fingerprint: 8c5127a75392be9cc9afd0dbae1222a673072c308c14d88ab246e23832e8c6bb
signature_date    : 2025-06-24T15:23:47.000000
signed_attributes : package,version,architecture,section,priority,name,categories,maintainer,description,depends,conflicts,maturity,locale,target_os,min_wapt_version,sources,installed_size,impacted_process,description_fr,description_pl,description_de,description_es,description_pt,description_it,description_nl,description_ru,audit_schedule,editor,keywords,licence,homepage,package_uuid,valid_from,valid_until,forced_install_on,changelog,min_os_version,max_os_version,icon_sha256sum,signer,signer_fingerprint,signature_date,signed_attributes
signature         : U8nki539H18jB54rgNtrndnNu2UBeSVR4FlgGDKVs7TYKbVR7d+8KDPkHKLbkyBCnaMGp72VsjUHkoPoX/Q8naw/fE5eClOZXkVwj5eaWXCDh9S20B4YSJdtEabqLDZ9Yt3QGlhQP5BVY+f0KI7qB3j1azb7MXYGmjpQ4dm5uIUEZ9QjNU/5y1WJxTF6TUMXvERl40vYmlPlMnzXd8S/xg2xebRH9bGcwTfeziEcMHyqRkeatuauuLI2Kr5DL9kV4h7veRyAwnskyFJhfflKESyB98mwoDky6ahy0NfG30cW7fOupSoJqeTAWaJY2Gj0fkMZWDRnN/eWUML8wXIEvQ==

# -*- coding: UTF-8 -*-
from setuphelpers import *
import time

# Installation procedure: https://firefox-source-docs.mozilla.org/browser/installer/windows/installer/FullConfig.html
# Configuration procedure: https://support.mozilla.org/kb/customizing-firefox-using-policiesjson

dist_dir = "distribution"
dist_path = makepath(programfiles, "Mozilla Firefox", dist_dir)
ext_dir = "extensions"
ext_path = makepath(dist_path, ext_dir)
policies_file = "policies.json"
policies_path = makepath(dist_path, policies_file)
list_pre_installed_lang = ["fr", "en-GB", "es-ES", "de", "it"]  # Reminder: 'en-US' will be native


def install():
    bin_name = glob.glob("Firefox_Setup_*.exe")[0]
    app_uninstallkey = "Mozilla Firefox %s (%s en-US)" % (control.get_software_version(), control.architecture)

    # Uninstalling others versions
    for uninstall in installed_softwares(name="Mozilla Firefox"):
        if not control.architecture in uninstall["name"] or "ESR" in uninstall["name"]:
            print("Removing: %s" % (uninstall["name"]))
            killalltasks(control.get_impacted_process_list())
            run(uninstall_cmd(uninstall["key"]))
            time.sleep(15)  # Required for Firefox

    # Installing the software
    install_exe_if_needed(
        bin_name,
        silentflags="/S /PreventRebootRequired=false /TaskbarShortcut=false /DesktopShortcut=false /StartMenuShortcut=true /MaintenanceService=false /RegisterDefaultAgent=false /RemoveDistributionDir=false /OptionalExtensions=false",
        key=app_uninstallkey,
        min_version=control.get_software_version(),
    )

    # Making sure that Mozilla Maintenance Service is not installed
    for uninstall in installed_softwares(name="Mozilla Maintenance Service"):
        print("Removing: %s" % (uninstall["name"]))
        run(uninstall_cmd(uninstall["key"]))

    # Removing policies from registry since it bypass the policies.json file (source: https://support.mozilla.org/bm/questions/1236197)
    ffox_policies_reg_path = r"SOFTWARE\Policies\Mozilla\Firefox"
    if reg_key_exists(HKEY_LOCAL_MACHINE, ffox_policies_reg_path):
        registry_deletekey(HKEY_LOCAL_MACHINE, ffox_policies_reg_path, "", force=True, recursive=True)

    # Adding distribution folder for language packs, dictionaries, extensions and configuration
    if isdir(dist_path):
        remove_tree(dist_path)
    mkdirs(dist_path)
    filecopyto(makepath(basedir, policies_file), dist_path)
    copytree2(makepath(basedir, ext_dir), ext_path)

    # Changing default language
    data = json_load_file(policies_path)
    my_lang = get_language()
    for select_lang in list_pre_installed_lang:
        if my_lang in select_lang:
            if select_lang == "en-GB":
                select_lang = "en-US"
            default_lang = {"RequestedLocales": [select_lang]}
    data["policies"].update(default_lang)
    json_write_file(policies_path, data, indent=2)

# -*- coding: UTF-8 -*-
from setuphelpers import *
from setupdevhelpers import *
import requests
import waptlicences

dist_dir = "distribution"
dist_path = makepath(programfiles, "Mozilla Firefox", dist_dir)
ext_dir = "extensions"
ext_path = makepath(dist_path, ext_dir)
policies_file = "policies.json"
policies_path = makepath(dist_path, policies_file)
list_pre_installed_lang = ["fr", "en-GB", "es-ES", "de", "it"]  # Reminder: 'en-US' will be native

def update_package():
    # Declaring local variables
    package_updated = False
    proxies = get_proxies()
    if not proxies:
        proxies = get_proxies_from_wapt_console()
    app_name = control.name

    arch_dict = {"x64": "win64", "x86": "win", "all": "win"}
    policies_content = json_load_file(policies_file)

    # Getting the latest version from official sources
    download_url = requests.head(f"https://download.mozilla.org/?product=firefox-latest-ssl&os={arch_dict[control.architecture]}&lang=en-US", proxies=proxies).headers["Location"]
    latest_bin = download_url.rsplit("/", 1)[-1].replace("%20", "_")
    latest_bin_extension = latest_bin.rsplit('.', 1)[-1]
    version = download_url.split("/")[-4]

    # Downloading the latest binaries
    print("Latest %s version is: %s" % (app_name, version))
    print("Download URL is: %s" % download_url)
    if not isfile(latest_bin):
        print("Downloading: %s" % latest_bin)
        wget(download_url, latest_bin, proxies=proxies)
    else:
        print("Binary is present: %s" % latest_bin)

    expected_issuer = "Mozilla Corporation"
    sign_name = waptlicences.check_exe_signing_certificate(latest_bin)[0]
    if sign_name != expected_issuer:
        error(f'Bad issuer {sign_name} != {expected_issuer} ')

    # Changing the version of the package
    if Version(version) > Version(control.get_software_version()):
        print("Software version updated (from: %s to: %s)" % (control.get_software_version(), Version(version)))
        package_updated = True
    else:
        print("Software version up-to-date (%s)" % Version(version))
    control.set_software_version(version)
    control.save_control_to_wapt()

    # Deleting outdated binaries
    for f in glob.glob(f'*.{latest_bin_extension}'):
        if f != latest_bin:
            remove_file(f)

    # Remove existing extensions folder
    if isdir(ext_dir):
        remove_tree(ext_dir)

    download_firefox_language_pack(policies_content, proxies)
    download_firefox_dictionnary(policies_content, proxies)

    # Downloading ublock origin extensions
    wget("https://addons.mozilla.org/firefox/downloads/latest/ublock-origin/latest.xpi", makepath(ext_dir, "ublock-origin.xpi"), proxies=proxies)

    print(f"Creating {policies_file} file for language packs, dictionaries, extensions, and configuration")
    if isfile(policies_file):
        remove_file(policies_file)

    json_write_file(policies_file, policies_content, indent=4)

    # Validate or not the update-package-sources
    return package_updated

def download_firefox_language_pack(policies_content, proxies):

    print("\n### DOWNLOADING LANGUAGE PACK ###\n")

    url_api_lp = "https://services.addons.mozilla.org/api/v3/addons/language-tools/?app=firefox&type=language"
    print("API used for language packs is: " + url_api_lp)
    version_major = control.version.split("-")[0].split(".")[0]

    # Retrieved the download url of the language pack
    json_read = wgets(url_api_lp, proxies=proxies, as_json=True)
    
    for lang in list_pre_installed_lang:

        # Retrieve the download URL for the language pack
        url_lp = next((lp["url"] + "versions/" for lp in json_read["results"] if lp["target_locale"] == lang), None)

        if not url_lp:
            print(f"No URL found for language pack: {lang}")
            continue

        # Find the version-specific download link
        url_dl_lp = None
        for download_lp in bs_find_all(url_lp, "a", "class", "InstallButtonWrapper-download-link", proxies=proxies):
            if version_major in download_lp.get("href", ""):
                url_dl_lp = download_lp["href"]
                break

        # Check if a valid URL for the language pack was found
        if not url_dl_lp:
            print(f"No valid download link found for language pack: {lang}")
            continue

        lp_name = f"{lang}_language_pack.xpi"
        print(f"Download URL for language pack in {lang} is: {url_dl_lp}")
        wget(url_dl_lp, makepath(ext_dir, lp_name), proxies=proxies)

        policies_content["policies"]["ExtensionSettings"].update({
            f"langpack-{lang}@firefox.mozilla.org": {
                "install_url": f"file://{ext_path}\\{lang}_language_pack.xpi", 
                "installation_mode": "force_installed"
            }
        })

def download_firefox_dictionnary(policies_content, proxies):

    print("\n### DOWNLOADING DICTIONNARY ###\n")

    url_api_dict_lang = "https://services.addons.mozilla.org/api/v3/addons/language-tools/?app=firefox&type=dictionary"
    print("API used for language dictionaries is: " + url_api_dict_lang)

    json_read = wgets(url_api_dict_lang, proxies=proxies, as_json=True)

    for lang in list_pre_installed_lang:

        if lang == "de":
            lang = "de-DE"

        dict_lang = next((d for d in json_read["results"] if d["target_locale"] == lang), None)

        if not dict_lang:
            print(f"No dictionary found for language: {lang}")
            continue

        url_dl_dict_lang = f"https://addons.mozilla.org/firefox/downloads/latest/{dict_lang['slug']}/latest.xpi"
        ext_add_on_id = dict_lang["guid"]

        dict_lang_name = f"{lang}_dictionary.xpi"
        print(f"Download URL for dictionary in {lang} is: {url_dl_dict_lang}")
        wget(url_dl_dict_lang, makepath(ext_dir, dict_lang_name), proxies=proxies)

        policies_content["policies"]["ExtensionSettings"].update({
            ext_add_on_id: {
                "install_url": f"file://{ext_path}\\{dict_lang_name}", 
                "installation_mode": "force_installed"
                }
        })

48735ef5534b7b2c0bc4619af5925bb827064e143d6cd1983294ee65c560b4d3 : Firefox_Setup_140.0.exe
38d056ab130f7bf7c481c12636a4e9959de36561d3dfcbe54c6e3571bc0c1dc3 : WAPT/certificate.crt
db5b3bcc4712c40b18b465522783746547a5a0999d5f20033bbe424b6a27fb32 : WAPT/control
2dc82eade364831757e067169d0039e6e0c9b693f343ea9a62db709eb1942c9e : WAPT/icon.png
00ef6eb3c10171a87fb22ab6e516846678b73c56ae828cc19d11e32e43b8457a : extensions/de-DE_dictionary.xpi
3e78ee6d105273f2fc6be244bb72203e28b9586d99dbef5b946c93d9e5ed13f2 : extensions/de_language_pack.xpi
636a1cba4ac4193e4bbaa93773fa48675b580f9dcf6fa98a0bd685d44e697b1c : extensions/en-GB_dictionary.xpi
685f06bb4984124ffb66038f727d317c192cb553e738e5c720164b5d210c0013 : extensions/en-GB_language_pack.xpi
83a8f9117d7224728507d90990a7dfecd84a05aa55f9dd8ccc1bc199a163e739 : extensions/es-ES_dictionary.xpi
248a94ac5963f1c2dbaa2328afd70b0ca0e07659ddf20f2c2b7d3b1986368841 : extensions/es-ES_language_pack.xpi
e0e90b88b177dc1b268b019c8672eb1be943f12e174ad474dbdc46f0e6fbaa6f : extensions/fr_dictionary.xpi
2143fad99e98ce259471cc4ee1fc27405ec532dae3afcbb8675aaa569d58665c : extensions/fr_language_pack.xpi
90b173ffdde34a77108152a5ff51879767b1dd84e0aa0dfb7b2bab94cd2e7f53 : extensions/it_dictionary.xpi
7df517bcc3dc4f1a17e33389df19f37986dc86cab91a235bf8b7545e980fcfb9 : extensions/it_language_pack.xpi
b9e1c868bd1ac1defcabf2e01776d1a90effba34b07fe6a21350d45f022e0e9f : extensions/ublock-origin.xpi
7335ba9b43d558c253bbfe75af5e1d164f761a2be883be594d2b8f06ce5fd719 : luti.json
235c7795d36cf4c854ed0e8a4eadde6315457c6c9cf47238391757330be09d9e : policies.json
adc9b2bfc251776e43458be4184bcb1e28f8c684678fabafc1020d3dd27e2c07 : setup.py
e1c748605b036d72ccf16675ea84879b8d461f77ce8d7108c3cf2958f40113f5 : update_package.py