From 005d05005dd1dbddef98c457628781dceeb1a037 Mon Sep 17 00:00:00 2001 From: "Lauren N. Liberda" Date: Fri, 16 Dec 2022 19:38:37 +0100 Subject: [PATCH] add impersonate-chrome and impersonate-ff features initial support for curl-impersonate --- Cargo.toml | 2 ++ README.md | 3 +++ curl-sys/Cargo.toml | 2 ++ curl-sys/build.rs | 52 ++++++++++++++++++++++++++++++++++----------- 4 files changed, 47 insertions(+), 12 deletions(-) diff --git a/Cargo.toml b/Cargo.toml index 5fbe3a4b4..13b4238b6 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -54,6 +54,8 @@ zlib-ng-compat = ["curl-sys/zlib-ng-compat", "static-curl"] upkeep_7_62_0 = ["curl-sys/upkeep_7_62_0"] poll_7_68_0 = ["curl-sys/poll_7_68_0"] ntlm = ["curl-sys/ntlm"] +impersonate-chrome = ["curl-sys/impersonate-chrome"] +impersonate-ff = ["curl-sys/impersonate-ff"] [[test]] name = "atexit" diff --git a/README.md b/README.md index 6debe8979..3a7dee99f 100644 --- a/README.md +++ b/README.md @@ -134,6 +134,8 @@ with various Cargo features: - `poll_7_68_0`: Enable curl_multi_poll()/curl_multi_wakeup() support, requires curl 7.68.0 or later. Disabled by default. - `ntlm`: Enable NTLM support in curl. Disabled by default. - `windows-static-ssl`: Enable Openssl support on Windows via the static build provided by vcpkg. Incompatible with `ssl` (use `--no-default-features`). Disabled by default. +- `impersonate-chrome`: Use [curl-impersonate](curl-impersonate) in chrome flavor. Incompatible with `static-curl`, enforces built-in BoringSSL as TLS backend. +- `impersonate-ff`: Use [curl-impersonate](curl-impersonate) in firefox flavor. Incompatible with `static-curl`, enforces built-in NSS as TLS backend. Note that to install openssl on windows via vcpkg the following commands needs to be ran: ```shell @@ -182,3 +184,4 @@ details. [Rustls]: https://github.com/ctz/rustls [Schannel]: https://docs.microsoft.com/en-us/windows/win32/com/schannel [Secure Transport]: https://developer.apple.com/documentation/security/secure_transport +[curl-impersonate]: https://github.com/lwthiker/curl-impersonate diff --git a/curl-sys/Cargo.toml b/curl-sys/Cargo.toml index 1163e778b..731daf403 100644 --- a/curl-sys/Cargo.toml +++ b/curl-sys/Cargo.toml @@ -58,3 +58,5 @@ zlib-ng-compat = ["libz-sys/zlib-ng", "static-curl"] upkeep_7_62_0 = [] poll_7_68_0 = [] ntlm = [] +impersonate-chrome = [] +impersonate-ff = [] diff --git a/curl-sys/build.rs b/curl-sys/build.rs index 821959488..91066b12e 100644 --- a/curl-sys/build.rs +++ b/curl-sys/build.rs @@ -8,11 +8,31 @@ fn main() { let host = env::var("HOST").unwrap(); let target = env::var("TARGET").unwrap(); let windows = target.contains("windows"); + let curlname = if cfg!(feature = "impersonate-chrome") { + "curl-impersonate-chrome" + } else if cfg!(feature = "impersonate-ff") { + "curl-impersonate-ff" + } else { + "curl" + }; + let libname = format!("lib{curlname}"); + let configname = format!("{curlname}-config"); if cfg!(feature = "mesalink") { println!("cargo:warning=MesaLink support has been removed as of curl 7.82.0, will use default TLS backend instead."); } + if cfg!(feature = "impersonate-chrome") && cfg!(feature = "impersonate-ff") { + panic!("impersonate-chrome and impersonate-ff features cannot be both enabled"); + } + if (cfg!(feature = "impersonate-chrome") || cfg!(feature = "impersonate-ff")) + && cfg!(feature = "static-curl") + { + panic!( + "impersonate-chrome and impersonate-ff features don't work together with static-curl" + ); + } + // This feature trumps all others, and is largely set by rustbuild to force // usage of the system library to ensure that we're always building an // ABI-compatible Cargo. @@ -31,7 +51,9 @@ fn main() { if !cfg!(feature = "static-curl") { // OSX ships libcurl by default, so we just use that version // so long as it has the right features enabled. - if target.contains("apple") && (!cfg!(feature = "http2") || curl_config_reports_http2()) { + if target.contains("apple") + && (!cfg!(feature = "http2") || curl_config_reports_http2(&configname, &libname)) + { return println!("cargo:rustc-flags=-l curl"); } @@ -40,11 +62,17 @@ fn main() { if try_vcpkg() { return; } - } else if try_pkg_config() { + } else if try_pkg_config(&configname, &libname) { return; } } + if cfg!(feature = "impersonate-chrome") || cfg!(feature = "impersonate-ff") { + panic!( + "impersonate feature is enabled, but {} was not found in system. fallback to static not available", libname + ); + } + if !Path::new("curl/.git").exists() { let _ = Command::new("git") .args(&["submodule", "update", "--init"]) @@ -500,14 +528,14 @@ fn try_vcpkg() -> bool { false } -fn try_pkg_config() -> bool { +fn try_pkg_config(configname: &str, libname: &str) -> bool { let mut cfg = pkg_config::Config::new(); cfg.cargo_metadata(false); - let lib = match cfg.probe("libcurl") { + let lib = match cfg.probe(libname) { Ok(lib) => lib, Err(e) => { println!( - "Couldn't find libcurl from pkgconfig ({:?}), \ + "Couldn't find {libname} from pkgconfig ({:?}), \ compiling it from source...", e ); @@ -517,13 +545,13 @@ fn try_pkg_config() -> bool { // Not all system builds of libcurl have http2 features enabled, so if we've // got a http2-requested build then we may fall back to a build from source. - if cfg!(feature = "http2") && !curl_config_reports_http2() { + if cfg!(feature = "http2") && !curl_config_reports_http2(configname, libname) { return false; } // Re-find the library to print cargo's metadata, then print some extra // metadata as well. - cfg.cargo_metadata(true).probe("libcurl").unwrap(); + cfg.cargo_metadata(true).probe(libname).unwrap(); for path in lib.include_paths.iter() { println!("cargo:include={}", path.display()); } @@ -548,24 +576,24 @@ fn xcode_major_version() -> Option { None } -fn curl_config_reports_http2() -> bool { - let output = Command::new("curl-config").arg("--features").output(); +fn curl_config_reports_http2(configname: &str, libname: &str) -> bool { + let output = Command::new(configname).arg("--features").output(); let output = match output { Ok(out) => out, Err(e) => { - println!("failed to run curl-config ({}), building from source", e); + println!("failed to run {configname} ({}), building from source", e); return false; } }; if !output.status.success() { - println!("curl-config failed: {}", output.status); + println!("{configname} failed: {}", output.status); return false; } let stdout = String::from_utf8_lossy(&output.stdout); if !stdout.contains("HTTP2") { println!( "failed to find http-2 feature enabled in pkg-config-found \ - libcurl, building from source" + {libname}, building from source" ); return false; }