123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170 |
- // Copyright 2019-2023 Tauri Programme within The Commons Conservancy
- // SPDX-License-Identifier: Apache-2.0
- // SPDX-License-Identifier: MIT
- use std::{
- fs::{create_dir_all, File},
- io::{Cursor, Read, Write},
- path::{Path, PathBuf},
- };
- use log::info;
- use sha2::Digest;
- use zip::ZipArchive;
- pub const WEBVIEW2_BOOTSTRAPPER_URL: &str = "https://go.microsoft.com/fwlink/p/?LinkId=2124703";
- pub const WEBVIEW2_OFFLINE_INSTALLER_X86_URL: &str =
- "https://go.microsoft.com/fwlink/?linkid=2099617";
- pub const WEBVIEW2_OFFLINE_INSTALLER_X64_URL: &str =
- "https://go.microsoft.com/fwlink/?linkid=2124701";
- pub const WEBVIEW2_URL_PREFIX: &str =
- "https://msedge.sf.dl.delivery.mp.microsoft.com/filestreamingservice/files/";
- pub const NSIS_OUTPUT_FOLDER_NAME: &str = "nsis";
- pub const NSIS_UPDATER_OUTPUT_FOLDER_NAME: &str = "nsis-updater";
- pub const WIX_OUTPUT_FOLDER_NAME: &str = "msi";
- pub const WIX_UPDATER_OUTPUT_FOLDER_NAME: &str = "msi-updater";
- pub fn webview2_guid_path(url: &str) -> crate::Result<(String, String)> {
- let agent = ureq::AgentBuilder::new().try_proxy_from_env(true).build();
- let response = agent.head(url).call().map_err(Box::new)?;
- let final_url = response.get_url();
- let remaining_url = final_url.strip_prefix(WEBVIEW2_URL_PREFIX).ok_or_else(|| {
- anyhow::anyhow!(
- "WebView2 URL prefix mismatch. Expected `{}`, found `{}`.",
- WEBVIEW2_URL_PREFIX,
- final_url
- )
- })?;
- let (guid, filename) = remaining_url.split_once('/').ok_or_else(|| {
- anyhow::anyhow!(
- "WebView2 URL format mismatch. Expected `<GUID>/<FILENAME>`, found `{}`.",
- remaining_url
- )
- })?;
- Ok((guid.into(), filename.into()))
- }
- pub fn download_webview2_bootstrapper(base_path: &Path) -> crate::Result<PathBuf> {
- let file_path = base_path.join("MicrosoftEdgeWebview2Setup.exe");
- if !file_path.exists() {
- std::fs::write(&file_path, download(WEBVIEW2_BOOTSTRAPPER_URL)?)?;
- }
- Ok(file_path)
- }
- pub fn download_webview2_offline_installer(base_path: &Path, arch: &str) -> crate::Result<PathBuf> {
- let url = if arch == "x64" {
- WEBVIEW2_OFFLINE_INSTALLER_X64_URL
- } else {
- WEBVIEW2_OFFLINE_INSTALLER_X86_URL
- };
- let (guid, filename) = webview2_guid_path(url)?;
- let dir_path = base_path.join(guid);
- let file_path = dir_path.join(filename);
- if !file_path.exists() {
- create_dir_all(dir_path)?;
- std::fs::write(&file_path, download(url)?)?;
- }
- Ok(file_path)
- }
- pub fn download(url: &str) -> crate::Result<Vec<u8>> {
- info!(action = "Downloading"; "{}", url);
- let agent = ureq::AgentBuilder::new().try_proxy_from_env(true).build();
- let response = agent.get(url).call().map_err(Box::new)?;
- let mut bytes = Vec::new();
- response.into_reader().read_to_end(&mut bytes)?;
- Ok(bytes)
- }
- pub enum HashAlgorithm {
- #[cfg(target_os = "windows")]
- Sha256,
- Sha1,
- }
- /// Function used to download a file and checks SHA256 to verify the download.
- pub fn download_and_verify(
- url: &str,
- hash: &str,
- hash_algorithm: HashAlgorithm,
- ) -> crate::Result<Vec<u8>> {
- let data = download(url)?;
- info!("validating hash");
- match hash_algorithm {
- #[cfg(target_os = "windows")]
- HashAlgorithm::Sha256 => {
- let hasher = sha2::Sha256::new();
- verify(&data, hash, hasher)?;
- }
- HashAlgorithm::Sha1 => {
- let hasher = sha1::Sha1::new();
- verify(&data, hash, hasher)?;
- }
- }
- Ok(data)
- }
- fn verify(data: &Vec<u8>, hash: &str, mut hasher: impl Digest) -> crate::Result<()> {
- hasher.update(data);
- let url_hash = hasher.finalize().to_vec();
- let expected_hash = hex::decode(hash)?;
- if expected_hash == url_hash {
- Ok(())
- } else {
- Err(crate::Error::HashError)
- }
- }
- /// Extracts the zips from memory into a useable path.
- pub fn extract_zip(data: &[u8], path: &Path) -> crate::Result<()> {
- let cursor = Cursor::new(data);
- let mut zipa = ZipArchive::new(cursor)?;
- for i in 0..zipa.len() {
- let mut file = zipa.by_index(i)?;
- if let Some(name) = file.enclosed_name() {
- let dest_path = path.join(name);
- if file.is_dir() {
- create_dir_all(&dest_path)?;
- continue;
- }
- let parent = dest_path.parent().expect("Failed to get parent");
- if !parent.exists() {
- create_dir_all(parent)?;
- }
- let mut buff: Vec<u8> = Vec::new();
- file.read_to_end(&mut buff)?;
- let mut fileout = File::create(dest_path).expect("Failed to open file");
- fileout.write_all(&buff)?;
- }
- }
- Ok(())
- }
- #[cfg(target_os = "windows")]
- pub fn os_bitness<'a>() -> Option<&'a str> {
- use windows_sys::Win32::System::{
- Diagnostics::Debug::{PROCESSOR_ARCHITECTURE_AMD64, PROCESSOR_ARCHITECTURE_INTEL},
- SystemInformation::{GetNativeSystemInfo, SYSTEM_INFO},
- };
- let mut system_info: SYSTEM_INFO = unsafe { std::mem::zeroed() };
- unsafe { GetNativeSystemInfo(&mut system_info) };
- match unsafe { system_info.Anonymous.Anonymous.wProcessorArchitecture } {
- PROCESSOR_ARCHITECTURE_INTEL => Some("x86"),
- PROCESSOR_ARCHITECTURE_AMD64 => Some("x64"),
- _ => None,
- }
- }
|