diff --git a/checked_cli/Cargo.lock b/checked_cli/Cargo.lock index b1f4294..7e49971 100644 --- a/checked_cli/Cargo.lock +++ b/checked_cli/Cargo.lock @@ -449,8 +449,11 @@ dependencies = [ "dirs", "holochain_client", "minisign", + "reqwest 0.12.2", "rpassword", "tempfile", + "tokio", + "url", ] [[package]] @@ -1519,6 +1522,25 @@ dependencies = [ "tracing", ] +[[package]] +name = "h2" +version = "0.4.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "51ee2dd2e4f378392eeff5d51618cd9a63166a2513846bbc55f21cfacd9199d4" +dependencies = [ + "bytes", + "fnv", + "futures-core", + "futures-sink", + "futures-util", + "http 1.1.0", + "indexmap 2.2.6", + "slab", + "tokio", + "tokio-util", + "tracing", +] + [[package]] name = "hashbrown" version = "0.12.3" @@ -2060,6 +2082,29 @@ dependencies = [ "pin-project-lite", ] +[[package]] +name = "http-body" +version = "1.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1cac85db508abc24a2e48553ba12a996e87244a0395ce011e62b37158745d643" +dependencies = [ + "bytes", + "http 1.1.0", +] + +[[package]] +name = "http-body-util" +version = "0.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0475f8b2ac86659c21b64320d5d653f9efe42acd2a4e560073ec61a155a34f1d" +dependencies = [ + "bytes", + "futures-core", + "http 1.1.0", + "http-body 1.0.0", + "pin-project-lite", +] + [[package]] name = "httparse" version = "1.8.0" @@ -2082,9 +2127,9 @@ dependencies = [ "futures-channel", "futures-core", "futures-util", - "h2", + "h2 0.3.25", "http 0.2.12", - "http-body", + "http-body 0.4.6", "httparse", "httpdate", "itoa", @@ -2096,6 +2141,26 @@ dependencies = [ "want", ] +[[package]] +name = "hyper" +version = "1.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "186548d73ac615b32a73aafe38fb4f56c0d340e110e5a200bcadbaf2e199263a" +dependencies = [ + "bytes", + "futures-channel", + "futures-util", + "h2 0.4.3", + "http 1.1.0", + "http-body 1.0.0", + "httparse", + "itoa", + "pin-project-lite", + "smallvec 1.13.2", + "tokio", + "want", +] + [[package]] name = "hyper-tls" version = "0.5.0" @@ -2103,12 +2168,48 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "d6183ddfa99b85da61a140bea0efc93fdf56ceaa041b37d553518030827f9905" dependencies = [ "bytes", - "hyper", + "hyper 0.14.28", "native-tls", "tokio", "tokio-native-tls", ] +[[package]] +name = "hyper-tls" +version = "0.6.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "70206fc6890eaca9fde8a0bf71caa2ddfc9fe045ac9e5c70df101a7dbde866e0" +dependencies = [ + "bytes", + "http-body-util", + "hyper 1.2.0", + "hyper-util", + "native-tls", + "tokio", + "tokio-native-tls", + "tower-service", +] + +[[package]] +name = "hyper-util" +version = "0.1.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ca38ef113da30126bbff9cd1705f9273e15d45498615d138b0c20279ac7a76aa" +dependencies = [ + "bytes", + "futures-channel", + "futures-util", + "http 1.1.0", + "http-body 1.0.0", + "hyper 1.2.0", + "pin-project-lite", + "socket2", + "tokio", + "tower", + "tower-service", + "tracing", +] + [[package]] name = "iana-time-zone" version = "0.1.60" @@ -2730,7 +2831,7 @@ dependencies = [ "flate2", "futures", "holochain_util", - "reqwest", + "reqwest 0.11.27", "rmp-serde", "serde", "serde_bytes", @@ -3750,11 +3851,53 @@ dependencies = [ "encoding_rs", "futures-core", "futures-util", - "h2", + "h2 0.3.25", "http 0.2.12", - "http-body", - "hyper", - "hyper-tls", + "http-body 0.4.6", + "hyper 0.14.28", + "hyper-tls 0.5.0", + "ipnet", + "js-sys", + "log", + "mime", + "native-tls", + "once_cell", + "percent-encoding", + "pin-project-lite", + "rustls-pemfile", + "serde", + "serde_json", + "serde_urlencoded", + "sync_wrapper", + "system-configuration", + "tokio", + "tokio-native-tls", + "tower-service", + "url", + "wasm-bindgen", + "wasm-bindgen-futures", + "web-sys", + "winreg", +] + +[[package]] +name = "reqwest" +version = "0.12.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2d66674f2b6fb864665eea7a3c1ac4e3dfacd2fda83cf6f935a612e01b0e3338" +dependencies = [ + "base64 0.21.7", + "bytes", + "encoding_rs", + "futures-core", + "futures-util", + "h2 0.4.3", + "http 1.1.0", + "http-body 1.0.0", + "http-body-util", + "hyper 1.2.0", + "hyper-tls 0.6.0", + "hyper-util", "ipnet", "js-sys", "log", @@ -4867,9 +5010,9 @@ checksum = "1f3ccbac311fea05f86f61904b462b55fb3df8837a366dfc601a0161d0532f20" [[package]] name = "tokio" -version = "1.36.0" +version = "1.37.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "61285f6515fa018fb2d1e46eb21223fff441ee8db5d0f1435e8ab4f5cdb80931" +checksum = "1adbebffeca75fcfd058afa480fb6c0b81e165a0323f9c9d39c9697e37c46787" dependencies = [ "backtrace", "bytes", @@ -4978,6 +5121,28 @@ dependencies = [ "walkdir", ] +[[package]] +name = "tower" +version = "0.4.13" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b8fa9be0de6cf49e536ce1851f987bd21a43b771b09473c3549a6c853db37c1c" +dependencies = [ + "futures-core", + "futures-util", + "pin-project", + "pin-project-lite", + "tokio", + "tower-layer", + "tower-service", + "tracing", +] + +[[package]] +name = "tower-layer" +version = "0.3.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c20c8dbed6283a09604c3e69b4b7eeb54e298b8a600d4d5ecb5ad39de609f1d0" + [[package]] name = "tower-service" version = "0.3.2" @@ -4990,6 +5155,7 @@ version = "0.1.40" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "c3523ab5a71916ccf420eebdf5521fcef02141234bbc0b8a49f2fdc4544364ef" dependencies = [ + "log", "pin-project-lite", "tracing-attributes", "tracing-core", diff --git a/checked_cli/Cargo.toml b/checked_cli/Cargo.toml index cc0cf3b..456d690 100644 --- a/checked_cli/Cargo.toml +++ b/checked_cli/Cargo.toml @@ -11,6 +11,10 @@ holochain_client = { version = "=0.5.0-dev.31", default-features = false } anyhow = "1.0.81" clap = { version = "4.5.2", features = ["derive", "cargo"] } minisign = "0.7.6" +reqwest = "0.12.2" +tempfile = "3.10.1" +tokio = "1.37.0" +url = "2.5.0" [target.'cfg(any(windows, unix))'.dependencies] dirs = "5.0.1" diff --git a/checked_cli/src/bin/checked.rs b/checked_cli/src/bin/checked.rs index 26b2461..68b95d1 100644 --- a/checked_cli/src/bin/checked.rs +++ b/checked_cli/src/bin/checked.rs @@ -1,7 +1,8 @@ use checked_cli::prelude::*; use clap::Parser; -fn main() -> anyhow::Result<()> { +#[tokio::main] +async fn main() -> anyhow::Result<()> { let cli = Cli::parse(); match cli.command { @@ -10,6 +11,7 @@ fn main() -> anyhow::Result<()> { } Commands::Sign(sign_args) => sign(sign_args)?, Commands::Verify(verify_args) => verify(verify_args)?, + Commands::Fetch(fetch_args) => fetch(fetch_args).await?, } Ok(()) diff --git a/checked_cli/src/cli.rs b/checked_cli/src/cli.rs index b5f6ca0..d527492 100644 --- a/checked_cli/src/cli.rs +++ b/checked_cli/src/cli.rs @@ -18,6 +18,9 @@ pub enum Commands { /// Verify a file Verify(VerifyArgs), + + /// Fetch an asset from a URL and check signatures for it + Fetch(FetchArgs), } #[derive(clap::Args)] @@ -86,3 +89,9 @@ pub struct VerifyArgs { #[arg(long, short)] pub signature: Option, } + +#[derive(clap::Args)] +pub struct FetchArgs { + #[arg()] + pub url: String, +} diff --git a/checked_cli/src/fetch.rs b/checked_cli/src/fetch.rs new file mode 100644 index 0000000..4e4b706 --- /dev/null +++ b/checked_cli/src/fetch.rs @@ -0,0 +1,46 @@ +use crate::cli::FetchArgs; +use anyhow::Context; + +pub async fn fetch(fetch_args: FetchArgs) -> anyhow::Result<()> { + let fetch_url = url::Url::parse(&fetch_args.url).context("Invalid URL")?; + let tmp_file = tempfile::Builder::new() + .prefix("checked-") + .suffix(".unverified") + .tempfile() + .context("Could not create temporary file")?; + + let client = reqwest::Client::new(); + + let resp = client + .head(fetch_url.clone()) + .send() + .await? + .error_for_status()?; + + let content_length = resp + .headers() + .get("content-length") + .and_then(|l| l.to_str().ok()) + .and_then(|l| l.parse::().ok()) + .unwrap_or(0); + + println!("Content length: {}", content_length); + + let mut res = reqwest::get(fetch_args.url).await?; + + while let Some(c) = res.chunk()? { + tmp_file.as_file_mut().write_all(&c)?; + } + + println!("Did initial request"); + + let content = res.bytes().await?; + + println!("Reading body"); + + std::io::copy(&mut content.as_ref(), &mut tmp_file.as_file())?; + + println!("Downloaded to {:?}", tmp_file.path()); + + Ok(()) +} diff --git a/checked_cli/src/lib.rs b/checked_cli/src/lib.rs index 7fe442f..c97e25e 100644 --- a/checked_cli/src/lib.rs +++ b/checked_cli/src/lib.rs @@ -5,10 +5,12 @@ pub mod generate; mod password; pub mod sign; pub mod verify; +mod fetch; pub mod prelude { pub use crate::cli::{Cli, Commands, GenerateArgs, SignArgs}; pub use crate::generate::generate; pub use crate::sign::sign; pub use crate::verify::verify; + pub use crate::fetch::fetch; }