mirror of
https://github.com/tauri-apps/tauri.git
synced 2024-08-16 19:30:27 +03:00
fix(NSIS): rewrite license file with BOM (#10049)
* fix(NSIS): rewrite license file with BOM closes #9031 This also includes a change to NSIS bundler to use UTF8 by default * refactor and cleanup
This commit is contained in:
parent
b2ff840e83
commit
3fd84cb3c9
5
.changes/bundler-nsis-license-file-bom.md
Normal file
5
.changes/bundler-nsis-license-file-bom.md
Normal file
@ -0,0 +1,5 @@
|
|||||||
|
---
|
||||||
|
'tauri-bundler': 'patch:bug'
|
||||||
|
---
|
||||||
|
|
||||||
|
Fix encoding of NSIS license page when using a license file without a BOM.
|
@ -21,7 +21,7 @@ use handlebars::{to_json, Handlebars};
|
|||||||
use tauri_utils::config::{NSISInstallerMode, NsisCompression, WebviewInstallMode};
|
use tauri_utils::config::{NSISInstallerMode, NsisCompression, WebviewInstallMode};
|
||||||
|
|
||||||
use std::{
|
use std::{
|
||||||
collections::{BTreeMap, HashMap},
|
collections::BTreeMap,
|
||||||
fs,
|
fs,
|
||||||
path::{Path, PathBuf},
|
path::{Path, PathBuf},
|
||||||
process::Command,
|
process::Command,
|
||||||
@ -213,31 +213,35 @@ fn build_nsis_app_installer(
|
|||||||
to_json(settings.windows().allow_downgrades),
|
to_json(settings.windows().allow_downgrades),
|
||||||
);
|
);
|
||||||
|
|
||||||
if let Some(license) = settings.license_file() {
|
if let Some(license_file) = settings.license_file() {
|
||||||
data.insert("license", to_json(dunce::canonicalize(license)?));
|
let license_file = dunce::canonicalize(license_file)?;
|
||||||
|
let license_file_with_bom = output_path.join("license_file");
|
||||||
|
let content = std::fs::read(license_file)?;
|
||||||
|
write_utf8_with_bom(&license_file_with_bom, content)?;
|
||||||
|
data.insert("license", to_json(license_file_with_bom));
|
||||||
}
|
}
|
||||||
|
|
||||||
let mut install_mode = NSISInstallerMode::CurrentUser;
|
let nsis = settings.windows().nsis.as_ref();
|
||||||
let mut languages = vec!["English".into()];
|
|
||||||
let mut custom_template_path = None;
|
let custom_template_path = nsis.as_ref().and_then(|n| n.template.clone());
|
||||||
let mut custom_language_files = None;
|
|
||||||
if let Some(nsis) = &settings.windows().nsis {
|
let install_mode = nsis
|
||||||
custom_template_path.clone_from(&nsis.template);
|
.as_ref()
|
||||||
custom_language_files.clone_from(&nsis.custom_language_files);
|
.map(|n| n.install_mode)
|
||||||
install_mode = nsis.install_mode;
|
.unwrap_or(NSISInstallerMode::CurrentUser);
|
||||||
if let Some(langs) = &nsis.languages {
|
|
||||||
languages.clear();
|
if let Some(nsis) = nsis {
|
||||||
languages.extend_from_slice(langs);
|
|
||||||
}
|
|
||||||
if let Some(installer_icon) = &nsis.installer_icon {
|
if let Some(installer_icon) = &nsis.installer_icon {
|
||||||
data.insert(
|
data.insert(
|
||||||
"installer_icon",
|
"installer_icon",
|
||||||
to_json(dunce::canonicalize(installer_icon)?),
|
to_json(dunce::canonicalize(installer_icon)?),
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
if let Some(header_image) = &nsis.header_image {
|
if let Some(header_image) = &nsis.header_image {
|
||||||
data.insert("header_image", to_json(dunce::canonicalize(header_image)?));
|
data.insert("header_image", to_json(dunce::canonicalize(header_image)?));
|
||||||
}
|
}
|
||||||
|
|
||||||
if let Some(sidebar_image) = &nsis.sidebar_image {
|
if let Some(sidebar_image) = &nsis.sidebar_image {
|
||||||
data.insert(
|
data.insert(
|
||||||
"sidebar_image",
|
"sidebar_image",
|
||||||
@ -245,11 +249,6 @@ fn build_nsis_app_installer(
|
|||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
data.insert(
|
|
||||||
"display_language_selector",
|
|
||||||
to_json(nsis.display_language_selector && languages.len() > 1),
|
|
||||||
);
|
|
||||||
|
|
||||||
if let Some(installer_hooks) = &nsis.installer_hooks {
|
if let Some(installer_hooks) = &nsis.installer_hooks {
|
||||||
let installer_hooks = dunce::canonicalize(installer_hooks)?;
|
let installer_hooks = dunce::canonicalize(installer_hooks)?;
|
||||||
data.insert("installer_hooks", to_json(installer_hooks));
|
data.insert("installer_hooks", to_json(installer_hooks));
|
||||||
@ -281,26 +280,48 @@ fn build_nsis_app_installer(
|
|||||||
}),
|
}),
|
||||||
);
|
);
|
||||||
|
|
||||||
let mut languages_data = Vec::new();
|
let languages = nsis
|
||||||
for lang in &languages {
|
.and_then(|nsis| nsis.languages.clone())
|
||||||
if let Some(data) = get_lang_data(lang, custom_language_files.as_ref())? {
|
.unwrap_or_else(|| vec!["English".into()]);
|
||||||
languages_data.push(data);
|
|
||||||
} else {
|
|
||||||
log::warn!("Custom tauri messages for {lang} are not translated.\nIf it is a valid language listed on <https://github.com/kichik/nsis/tree/9465c08046f00ccb6eda985abbdbf52c275c6c4d/Contrib/Language%20files>, please open a Tauri feature request\n or you can provide a custom language file for it in `tauri.conf.json > bundle > windows > nsis > custom_language_files`");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
data.insert("languages", to_json(languages.clone()));
|
data.insert("languages", to_json(languages.clone()));
|
||||||
|
|
||||||
data.insert(
|
data.insert(
|
||||||
"language_files",
|
"display_language_selector",
|
||||||
to_json(
|
to_json(
|
||||||
languages_data
|
nsis
|
||||||
.iter()
|
.map(|nsis| nsis.display_language_selector && languages.len() > 1)
|
||||||
.map(|d| d.0.clone())
|
.unwrap_or(false),
|
||||||
.collect::<Vec<_>>(),
|
|
||||||
),
|
),
|
||||||
);
|
);
|
||||||
|
|
||||||
|
let custom_language_files = nsis.and_then(|nsis| nsis.custom_language_files.clone());
|
||||||
|
|
||||||
|
let mut language_files_paths = Vec::new();
|
||||||
|
for lang in &languages {
|
||||||
|
// if user provided a custom lang file, we rewrite it with BOM
|
||||||
|
if let Some(path) = custom_language_files.as_ref().and_then(|h| h.get(lang)) {
|
||||||
|
let path = dunce::canonicalize(path)?;
|
||||||
|
let path_with_bom = path
|
||||||
|
.file_name()
|
||||||
|
.map(|f| output_path.join(f))
|
||||||
|
.unwrap_or_else(|| output_path.join(format!("{lang}_custom.nsh")));
|
||||||
|
let content = std::fs::read(path)?;
|
||||||
|
write_utf8_with_bom(&path_with_bom, content)?;
|
||||||
|
language_files_paths.push(path_with_bom);
|
||||||
|
} else {
|
||||||
|
// if user has not provided a custom lang file,
|
||||||
|
// we check our translated languages
|
||||||
|
if let Some((file_name, content)) = get_lang_data(lang) {
|
||||||
|
let path = output_path.join(file_name);
|
||||||
|
write_utf8_with_bom(&path, content)?;
|
||||||
|
language_files_paths.push(path);
|
||||||
|
} else {
|
||||||
|
log::warn!("Custom tauri messages for {lang} are not translated.\nIf it is a valid language listed on <https://github.com/kichik/nsis/tree/9465c08046f00ccb6eda985abbdbf52c275c6c4d/Contrib/Language%20files>, please open a Tauri feature request\n or you can provide a custom language file for it in `tauri.conf.json > bundle > windows > nsis > custom_language_files`");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
data.insert("language_files", to_json(language_files_paths));
|
||||||
|
|
||||||
let main_binary = settings
|
let main_binary = settings
|
||||||
.binaries()
|
.binaries()
|
||||||
.iter()
|
.iter()
|
||||||
@ -463,27 +484,21 @@ fn build_nsis_app_installer(
|
|||||||
.expect("Failed to setup handlebar template");
|
.expect("Failed to setup handlebar template");
|
||||||
}
|
}
|
||||||
|
|
||||||
write_ut16_le_with_bom(
|
write_utf8_with_bom(
|
||||||
output_path.join("FileAssociation.nsh"),
|
output_path.join("FileAssociation.nsh"),
|
||||||
include_str!("./templates/FileAssociation.nsh"),
|
include_bytes!("./templates/FileAssociation.nsh"),
|
||||||
)?;
|
)?;
|
||||||
write_ut16_le_with_bom(
|
write_utf8_with_bom(
|
||||||
output_path.join("utils.nsh"),
|
output_path.join("utils.nsh"),
|
||||||
include_str!("./templates/utils.nsh"),
|
include_bytes!("./templates/utils.nsh"),
|
||||||
)?;
|
)?;
|
||||||
|
|
||||||
let installer_nsi_path = output_path.join("installer.nsi");
|
let installer_nsi_path = output_path.join("installer.nsi");
|
||||||
write_ut16_le_with_bom(
|
write_utf8_with_bom(
|
||||||
&installer_nsi_path,
|
&installer_nsi_path,
|
||||||
handlebars.render("installer.nsi", &data)?.as_str(),
|
handlebars.render("installer.nsi", &data)?,
|
||||||
)?;
|
)?;
|
||||||
|
|
||||||
for (lang, data) in languages_data.iter() {
|
|
||||||
if let Some(content) = data {
|
|
||||||
write_ut16_le_with_bom(output_path.join(lang).with_extension("nsh"), content)?;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
let package_base_name = format!(
|
let package_base_name = format!(
|
||||||
"{}_{}_{}-setup",
|
"{}_{}_{}-setup",
|
||||||
settings.product_name(),
|
settings.product_name(),
|
||||||
@ -511,6 +526,7 @@ fn build_nsis_app_installer(
|
|||||||
let mut nsis_cmd = Command::new("makensis");
|
let mut nsis_cmd = Command::new("makensis");
|
||||||
|
|
||||||
nsis_cmd
|
nsis_cmd
|
||||||
|
.args(["-INPUTCHARSET", "UTF8", "-OUTPUTCHARSET", "UTF8"])
|
||||||
.arg(match settings.log_level() {
|
.arg(match settings.log_level() {
|
||||||
log::Level::Error => "-V1",
|
log::Level::Error => "-V1",
|
||||||
log::Level::Warn => "-V2",
|
log::Level::Warn => "-V2",
|
||||||
@ -662,50 +678,38 @@ fn generate_estimated_size(
|
|||||||
Ok(format!("{size:#08x}"))
|
Ok(format!("{size:#08x}"))
|
||||||
}
|
}
|
||||||
|
|
||||||
fn get_lang_data(
|
fn get_lang_data(lang: &str) -> Option<(String, &[u8])> {
|
||||||
lang: &str,
|
let path = format!("{lang}.nsh");
|
||||||
custom_lang_files: Option<&HashMap<String, PathBuf>>,
|
let content: &[u8] = match lang.to_lowercase().as_str() {
|
||||||
) -> crate::Result<Option<(PathBuf, Option<&'static str>)>> {
|
"arabic" => include_bytes!("./templates/nsis-languages/Arabic.nsh"),
|
||||||
if let Some(path) = custom_lang_files.and_then(|h| h.get(lang)) {
|
"bulgarian" => include_bytes!("./templates/nsis-languages/Bulgarian.nsh"),
|
||||||
return Ok(Some((dunce::canonicalize(path)?, None)));
|
"dutch" => include_bytes!("./templates/nsis-languages/Dutch.nsh"),
|
||||||
}
|
"english" => include_bytes!("./templates/nsis-languages/English.nsh"),
|
||||||
|
"german" => include_bytes!("./templates/nsis-languages/German.nsh"),
|
||||||
let lang_path = PathBuf::from(format!("{lang}.nsh"));
|
"japanese" => include_bytes!("./templates/nsis-languages/Japanese.nsh"),
|
||||||
let lang_content = match lang.to_lowercase().as_str() {
|
"korean" => include_bytes!("./templates/nsis-languages/Korean.nsh"),
|
||||||
"arabic" => Some(include_str!("./templates/nsis-languages/Arabic.nsh")),
|
"portuguesebr" => include_bytes!("./templates/nsis-languages/PortugueseBR.nsh"),
|
||||||
"bulgarian" => Some(include_str!("./templates/nsis-languages/Bulgarian.nsh")),
|
"russian" => include_bytes!("./templates/nsis-languages/Russian.nsh"),
|
||||||
"dutch" => Some(include_str!("./templates/nsis-languages/Dutch.nsh")),
|
"tradchinese" => include_bytes!("./templates/nsis-languages/TradChinese.nsh"),
|
||||||
"english" => Some(include_str!("./templates/nsis-languages/English.nsh")),
|
"simpchinese" => include_bytes!("./templates/nsis-languages/SimpChinese.nsh"),
|
||||||
"german" => Some(include_str!("./templates/nsis-languages/German.nsh")),
|
"french" => include_bytes!("./templates/nsis-languages/French.nsh"),
|
||||||
"japanese" => Some(include_str!("./templates/nsis-languages/Japanese.nsh")),
|
"spanish" => include_bytes!("./templates/nsis-languages/Spanish.nsh"),
|
||||||
"korean" => Some(include_str!("./templates/nsis-languages/Korean.nsh")),
|
"spanishinternational" => include_bytes!("./templates/nsis-languages/SpanishInternational.nsh"),
|
||||||
"portuguesebr" => Some(include_str!("./templates/nsis-languages/PortugueseBR.nsh")),
|
"persian" => include_bytes!("./templates/nsis-languages/Persian.nsh"),
|
||||||
"russian" => Some(include_str!("./templates/nsis-languages/Russian.nsh")),
|
"turkish" => include_bytes!("./templates/nsis-languages/Turkish.nsh"),
|
||||||
"tradchinese" => Some(include_str!("./templates/nsis-languages/TradChinese.nsh")),
|
"swedish" => include_bytes!("./templates/nsis-languages/Swedish.nsh"),
|
||||||
"simpchinese" => Some(include_str!("./templates/nsis-languages/SimpChinese.nsh")),
|
_ => return None,
|
||||||
"french" => Some(include_str!("./templates/nsis-languages/French.nsh")),
|
|
||||||
"spanish" => Some(include_str!("./templates/nsis-languages/Spanish.nsh")),
|
|
||||||
"spanishinternational" => Some(include_str!(
|
|
||||||
"./templates/nsis-languages/SpanishInternational.nsh"
|
|
||||||
)),
|
|
||||||
"persian" => Some(include_str!("./templates/nsis-languages/Persian.nsh")),
|
|
||||||
"turkish" => Some(include_str!("./templates/nsis-languages/Turkish.nsh")),
|
|
||||||
"swedish" => Some(include_str!("./templates/nsis-languages/Swedish.nsh")),
|
|
||||||
_ => return Ok(None),
|
|
||||||
};
|
};
|
||||||
|
Some((path, content))
|
||||||
Ok(Some((lang_path, lang_content)))
|
|
||||||
}
|
}
|
||||||
|
|
||||||
fn write_ut16_le_with_bom<P: AsRef<Path>>(path: P, content: &str) -> crate::Result<()> {
|
fn write_utf8_with_bom<P: AsRef<Path>, C: AsRef<[u8]>>(path: P, content: C) -> crate::Result<()> {
|
||||||
use std::fs::File;
|
use std::fs::File;
|
||||||
use std::io::{BufWriter, Write};
|
use std::io::{BufWriter, Write};
|
||||||
|
|
||||||
let file = File::create(path)?;
|
let file = File::create(path)?;
|
||||||
let mut output = BufWriter::new(file);
|
let mut output = BufWriter::new(file);
|
||||||
output.write_all(&[0xFF, 0xFE])?; // the BOM part
|
output.write_all(&[0xEF, 0xBB, 0xBF])?; // UTF-8 BOM
|
||||||
for utf16 in content.encode_utf16() {
|
output.write_all(content.as_ref())?;
|
||||||
output.write_all(&utf16.to_le_bytes())?;
|
|
||||||
}
|
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
@ -157,7 +157,7 @@ pub fn sign_command_default<P: AsRef<Path>>(
|
|||||||
) -> crate::Result<Command> {
|
) -> crate::Result<Command> {
|
||||||
let signtool = signtool().ok_or(crate::Error::SignToolNotFound)?;
|
let signtool = signtool().ok_or(crate::Error::SignToolNotFound)?;
|
||||||
|
|
||||||
let mut cmd = Command::new(&signtool);
|
let mut cmd = Command::new(signtool);
|
||||||
cmd.arg("sign");
|
cmd.arg("sign");
|
||||||
cmd.args(["/fd", ¶ms.digest_algorithm]);
|
cmd.args(["/fd", ¶ms.digest_algorithm]);
|
||||||
cmd.args(["/sha1", ¶ms.certificate_thumbprint]);
|
cmd.args(["/sha1", ¶ms.certificate_thumbprint]);
|
||||||
|
Loading…
Reference in New Issue
Block a user