├── .gitignore ├── .gitmodules ├── Dockerfile ├── src ├── delete.rs ├── util.rs ├── message.rs ├── wire.rs ├── migrations │ └── mod.rs ├── query.rs ├── main.rs └── db.rs ├── Cargo.toml ├── LICENSE ├── README.md └── Cargo.lock /.gitignore: -------------------------------------------------------------------------------- 1 | /target 2 | **/*.rs.bk 3 | image.tar 4 | cups.s9pk 5 | assets/www 6 | -------------------------------------------------------------------------------- /.gitmodules: -------------------------------------------------------------------------------- 1 | [submodule "cups-messenger-ui"] 2 | path = cups-messenger-ui 3 | url = https://github.com/Start9Labs/cups-messenger-ui.git 4 | -------------------------------------------------------------------------------- /Dockerfile: -------------------------------------------------------------------------------- 1 | FROM alpine 2 | 3 | EXPOSE 59001 80 4 | 5 | RUN apk add lighttpd 6 | 7 | ADD ./target/release/cups /usr/local/bin/cups 8 | RUN chmod a+x /usr/local/bin/cups 9 | ADD ./docker_entrypoint.sh /usr/local/bin/docker_entrypoint.sh 10 | RUN chmod a+x /usr/local/bin/docker_entrypoint.sh 11 | 12 | ENTRYPOINT ["/usr/local/bin/docker_entrypoint.sh"] 13 | -------------------------------------------------------------------------------- /src/delete.rs: -------------------------------------------------------------------------------- 1 | use ed25519_dalek::PublicKey; 2 | use failure::Error; 3 | 4 | #[derive(Clone, Debug, serde::Deserialize)] 5 | #[serde(tag = "type")] 6 | #[serde(rename_all = "camelCase")] 7 | pub enum Query { 8 | User { pubkey: String }, 9 | } 10 | 11 | pub async fn handle(q: Query) -> Result<(), Error> { 12 | match q { 13 | Query::User { pubkey } => { 14 | crate::db::del_user(PublicKey::from_bytes( 15 | &base32::decode(base32::Alphabet::RFC4648 { padding: false }, &pubkey) 16 | .ok_or_else(|| failure::format_err!("invalid pubkey"))?, 17 | )?) 18 | .await 19 | } 20 | } 21 | } 22 | -------------------------------------------------------------------------------- /src/util.rs: -------------------------------------------------------------------------------- 1 | use std::fmt::Display; 2 | use std::str::FromStr; 3 | 4 | use serde::de::{Deserialize, Deserializer}; 5 | 6 | pub fn deser_parse<'de, E: Display, T: FromStr + Sized, D: Deserializer<'de>>( 7 | deserializer: D, 8 | ) -> Result { 9 | let s: String = Deserialize::deserialize(deserializer)?; 10 | s.parse().map_err(serde::de::Error::custom) 11 | } 12 | 13 | pub fn deser_parse_opt<'de, E: Display, T: FromStr + Sized, D: Deserializer<'de>>( 14 | deserializer: D, 15 | ) -> Result, D::Error> { 16 | let s: Option = Deserialize::deserialize(deserializer)?; 17 | s.map(|s| s.parse().map_err(serde::de::Error::custom)) 18 | .transpose() 19 | } 20 | -------------------------------------------------------------------------------- /Cargo.toml: -------------------------------------------------------------------------------- 1 | [package] 2 | authors = ["Aiden McClelland "] 3 | edition = "2018" 4 | name = "cups" 5 | version = "0.3.8" 6 | 7 | # See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html 8 | 9 | [dependencies] 10 | base32 = "0.4.0" 11 | base64 = "0.13.0" 12 | ed25519-dalek = "1.0.1" 13 | failure = "0.1.8" 14 | futures = "0.3.5" 15 | hyper = { version = "0.14.14", features = ["server"] } 16 | hyper-tls = "0.5.0" 17 | lazy_static = "1.4.0" 18 | openssl = { version = "0.10.35", features = ["vendored"] } 19 | parking_lot = "0.11.0" 20 | r2d2 = "0.8.9" 21 | r2d2_sqlite = "0.19.0" 22 | reqwest = { version = "0.11.6", features = ["socks"] } 23 | rusqlite = { version = "0.26.1", features = ["bundled", "blob", "uuid"] } 24 | serde = { version = "1.0", features = ["derive"] } 25 | serde_urlencoded = "0.7.0" 26 | serde_yaml = "0.8.21" 27 | sha3 = "0.9.1" 28 | tokio = { version = "1.13.0", features = ["full"] } 29 | uuid = "0.8.1" 30 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2024 Start9 Labs, Inc 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /src/message.rs: -------------------------------------------------------------------------------- 1 | use ed25519_dalek::PublicKey; 2 | use failure::Error; 3 | use uuid::Uuid; 4 | 5 | pub struct NewInboundMessage { 6 | pub from: PublicKey, 7 | pub time: i64, 8 | pub content: String, 9 | } 10 | 11 | pub struct NewOutboundMessage { 12 | pub tracking_id: Option, 13 | pub to: PublicKey, 14 | pub time: i64, 15 | pub content: String, 16 | } 17 | 18 | lazy_static::lazy_static! { 19 | static ref CLIENT: reqwest::Client = reqwest::Client::builder().proxy(crate::PROXY.clone()).build().expect("CLIENT"); 20 | } 21 | 22 | pub async fn send(msg: NewOutboundMessage) -> Result<(), Error> { 23 | use sha3::{Digest, Sha3_256}; 24 | 25 | let mut hasher = Sha3_256::new(); 26 | hasher.update(b".onion checksum"); 27 | hasher.update(msg.to.as_bytes()); 28 | hasher.update(&[3]); 29 | let mut onion = Vec::with_capacity(35); 30 | onion.extend_from_slice(msg.to.as_bytes()); 31 | onion.extend_from_slice(&hasher.finalize()[..2]); 32 | onion.push(3); 33 | let onion_str = 34 | base32::encode(base32::Alphabet::RFC4648 { padding: false }, &onion).to_lowercase(); 35 | let res = CLIENT 36 | .post(&format!("http://{}.onion:59001", onion_str)) 37 | .body(crate::wire::encode(&*crate::SECKEY, &msg)?) 38 | .send() 39 | .await? 40 | .status(); 41 | if !res.is_success() { 42 | eprintln!("ERROR SENDING TO http://{}.onion:59001", onion_str); 43 | failure::bail!("{}", res.canonical_reason().unwrap_or("UNKNOWN ERROR")) 44 | } 45 | crate::db::save_out_message(msg).await?; 46 | Ok(()) 47 | } 48 | 49 | pub async fn receive(msg: &[u8]) -> Result<(), Error> { 50 | let msg = crate::wire::parse(msg)?; 51 | crate::db::save_in_message(msg).await 52 | } 53 | -------------------------------------------------------------------------------- /src/wire.rs: -------------------------------------------------------------------------------- 1 | use std::convert::TryFrom; 2 | 3 | use ed25519_dalek::{ExpandedSecretKey, PublicKey, Signature, Verifier}; 4 | use failure::Error; 5 | 6 | use crate::message::{NewInboundMessage, NewOutboundMessage}; 7 | 8 | pub fn parse(bytes: &[u8]) -> Result { 9 | if bytes 10 | .get(0) 11 | .ok_or_else(|| std::io::Error::from(std::io::ErrorKind::UnexpectedEof))? 12 | != &0 13 | { 14 | failure::bail!("Unsupported version"); 15 | } 16 | let pubkey = PublicKey::from_bytes( 17 | bytes 18 | .get(1..33) 19 | .ok_or_else(|| std::io::Error::from(std::io::ErrorKind::UnexpectedEof))?, 20 | )?; 21 | let sig = Signature::try_from( 22 | bytes 23 | .get(33..97) 24 | .ok_or_else(|| std::io::Error::from(std::io::ErrorKind::UnexpectedEof))?, 25 | )?; 26 | let payload = bytes 27 | .get(97..) 28 | .ok_or_else(|| std::io::Error::from(std::io::ErrorKind::UnexpectedEof))?; 29 | pubkey.verify(&payload, &sig)?; 30 | let mut time_buf = [0; 8]; 31 | time_buf.clone_from_slice( 32 | payload 33 | .get(..8) 34 | .ok_or_else(|| std::io::Error::from(std::io::ErrorKind::UnexpectedEof))?, 35 | ); 36 | Ok(NewInboundMessage { 37 | from: pubkey, 38 | time: i64::from_be_bytes(time_buf), 39 | content: String::from_utf8( 40 | payload 41 | .get(8..) 42 | .ok_or_else(|| std::io::Error::from(std::io::ErrorKind::UnexpectedEof))? 43 | .to_vec(), 44 | )?, 45 | }) 46 | } 47 | 48 | pub fn encode(key: &ExpandedSecretKey, message: &NewOutboundMessage) -> Result, Error> { 49 | let mut res = Vec::with_capacity(101 + message.content.as_bytes().len()); 50 | let pubkey = PublicKey::from(key); 51 | res.push(0); 52 | res.extend_from_slice(pubkey.as_bytes()); 53 | res.extend_from_slice(&[0; 64]); 54 | res.extend_from_slice(&i64::to_be_bytes(message.time)); 55 | res.extend_from_slice(&message.content.as_bytes()); 56 | let sig = key.sign(&res[97..], &pubkey); 57 | res[33..97].clone_from_slice(&sig.to_bytes()); 58 | 59 | Ok(res) 60 | } 61 | -------------------------------------------------------------------------------- /src/migrations/mod.rs: -------------------------------------------------------------------------------- 1 | use failure::Error; 2 | use failure::ResultExt; 3 | use rusqlite::params; 4 | use rusqlite::OptionalExtension; 5 | 6 | pub async fn migrate() -> Result<(), Error> { 7 | tokio::task::spawn_blocking(move || { 8 | let mut gconn = crate::db::POOL.get()?; 9 | let conn = gconn.transaction()?; 10 | init(&conn)?; 11 | tracking_ids(&conn)?; 12 | conn.commit()?; 13 | Ok::<_, Error>(()) 14 | }) 15 | .await??; 16 | Ok(()) 17 | } 18 | 19 | pub fn init(conn: &rusqlite::Transaction) -> Result<(), Error> { 20 | let q = "SELECT count(name) FROM sqlite_master WHERE type = 'table' AND name = 'migrations'"; 21 | let exists: i64 = conn 22 | .query_row(q, params![], |row| row.get(0)) 23 | .with_context(|e| format!("{}: {}", q, e))?; 24 | let q = "SELECT * FROM migrations WHERE name = 'init'"; 25 | if exists == 0 26 | || conn 27 | .query_row(q, params![], |_| Ok(())) 28 | .optional() 29 | .with_context(|e| format!("{}: {}", q, e))? 30 | .is_none() 31 | { 32 | println!("EXECUTING init MIGRATION"); 33 | let q = "CREATE TABLE messages ( 34 | id INTEGER PRIMARY KEY AUTOINCREMENT, 35 | user_id BLOB NOT NULL, 36 | created_at TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP, 37 | inbound BOOLEAN NOT NULL, 38 | time INTEGER NOT NULL, 39 | content TEXT NOT NULL, 40 | read BOOLEAN NOT NULL DEFAULT FALSE 41 | )"; 42 | conn.execute(q, params![]) 43 | .with_context(|e| format!("{}: {}", q, e))?; 44 | let q = "CREATE TABLE users ( 45 | id BLOB PRIMARY KEY, 46 | name TEXT NOT NULL 47 | )"; 48 | conn.execute(q, params![]) 49 | .with_context(|e| format!("{}: {}", q, e))?; 50 | let q = "CREATE TABLE migrations ( 51 | time TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP, 52 | name TEXT 53 | )"; 54 | conn.execute(q, params![]) 55 | .with_context(|e| format!("{}: {}", q, e))?; 56 | let q = "INSERT INTO migrations (name) VALUES ('init')"; 57 | conn.execute(q, params![]) 58 | .with_context(|e| format!("{}: {}", q, e))?; 59 | } 60 | Ok(()) 61 | } 62 | 63 | pub fn tracking_ids(conn: &rusqlite::Transaction) -> Result<(), Error> { 64 | let q = "SELECT * FROM migrations WHERE name = 'tracking_ids'"; 65 | if conn 66 | .query_row(q, params![], |_| Ok(())) 67 | .optional() 68 | .with_context(|e| format!("{}: {}", q, e))? 69 | .is_none() 70 | { 71 | println!("EXECUTING tracking_ids MIGRATION"); 72 | let q = "ALTER TABLE messages ADD tracking_id BLOB"; 73 | conn.execute(q, params![]) 74 | .with_context(|e| format!("{}: {}", q, e))?; 75 | let q = "CREATE INDEX messages_user_id_idx ON messages(user_id)"; 76 | conn.execute(q, params![]) 77 | .with_context(|e| format!("{}: {}", q, e))?; 78 | let q = "CREATE INDEX messages_tracking_id_idx ON messages(tracking_id)"; 79 | conn.execute(q, params![]) 80 | .with_context(|e| format!("{}: {}", q, e))?; 81 | let q = "INSERT INTO migrations (name) VALUES ('tracking_ids')"; 82 | conn.execute(q, params![]) 83 | .with_context(|e| format!("{}: {}", q, e))?; 84 | } 85 | Ok(()) 86 | } 87 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # cups 2 | 3 | ## Building and running 4 | 5 | ### Start9 Embassy 6 | [Go Here](https://github.com/Start9Labs/cups-wrapper) 7 | 8 | ### Debian 9 | This guide assumes you are running a debian-based operating system and are logged in as root. 10 | 11 | - Clone the repo 12 | - `git clone https://github.com/Start9Labs/cups-messenger.git` 13 | - This document assumes you have cloned to `~/cups-messenger` 14 | - `cd ~/cups-messenger` 15 | - `git submodule update --init` 16 | - Install Tor 17 | - `apt install tor` 18 | - Set up Tor Hidden Service 19 | - `vim /etc/tor/torrc` 20 | - Add the following lines: 21 | ``` 22 | SOCKSPort 0.0.0.0:9050 # This makes your Tor proxy available to your network. If your server is not behind a NAT that you control, make sure to set a SOCKS policy, or bind to the host ip on the docker0 interface 23 | 24 | HiddenServiceDir /var/lib/tor/cups_service 25 | HiddenServicePort 80 127.0.0.1:80 26 | HiddenServicePort 59001 127.0.0.1:59001 27 | HiddenServiceVersion 3 28 | ``` 29 | - Restart Tor 30 | - `systemctl restart tor` 31 | - Create a mount point for the container 32 | - `mkdir -p /var/opt/cups/start9` 33 | - Write config file 34 | - `vim /var/opt/cups/start9/config.yaml` 35 | - Add `password: ` with the password you want to use 36 | - Build Cups UI 37 | - `cd cups-messenger-ui` 38 | - Build 39 | - `npm i` 40 | - `npm run build-prod` 41 | - Copy over result 42 | - `cp -r www ../assets/www` 43 | - Return to Cups 44 | - `cd ..` 45 | - Copy over assets 46 | - `cp -r assets/* /var/opt/cups` 47 | - Build cups server 48 | - Make sure you have the [Rust toolchain](https://rustup.rs) 49 | - `cargo build --release` 50 | - NOTE: the docker image is designed for musl. If you are not on a musl platform, you must cross compile. 51 | - [Here](https://github.com/messense/rust-musl-cross) is a useful tool for cross compiling to musl. 52 | - You must also replace `target/release` with `target//release` everywhere in this guide, as well as in nonembassy.Dockerfile 53 | - (Optional) `strip target/release/cups` 54 | - Install Docker 55 | - `apt install docker.io` 56 | - Build the Docker Image 57 | - `docker build . -f nonembassy.Dockerfile -t start9/cups` 58 | - Create the Docker Container 59 | ```bash 60 | docker create \ 61 | --restart unless-stopped \ 62 | --name cups \ 63 | --mount type=bind,src=/var/opt/cups,dst=/root \ 64 | --env TOR_ADDRESS=$(cat /var/lib/tor/cups_service/hostname | sed 's/\n*$//g') \ 65 | --env TOR_KEY=$(tail -c 64 /var/lib/tor/cups_service/hs_ed25519_secret_key | base32 -w0 | sed 's/\n*$//g') \ 66 | --net bridge \ 67 | start9/cups 68 | ``` 69 | - Start the Docker Container 70 | - `docker start cups` 71 | - Get IP address of the Docker Container 72 | - `docker inspect -f '{{range .NetworkSettings.Networks}}{{.IPAddress}}{{end}}' cups` 73 | - Update hidden service configuration with the container IP 74 | - `vim /etc/tor/torrc` 75 | - Change `127.0.0.1` in the HiddenServicePort config to the result of the previous step 76 | - Restart Tor 77 | - `systemctl restart tor` 78 | - Your cups tor address can be found by running `cat /var/lib/tor/cups_service/hostname` 79 | 80 | 81 | ## API 82 | 83 | ### Authorization 84 | 85 | Cups uses Basic Auth 86 | 87 | - The username is always `me`. 88 | - The password is defined in `./start9/config.yaml` 89 | 90 | ### Send Message 91 | 92 | #### Request 93 | 94 | `POST` with body `0x00 ` 95 | 96 | ### Name User 97 | 98 | #### Request 99 | 100 | `POST` with body `0x01 ` 101 | 102 | ### Get Contact Book 103 | 104 | #### Request 105 | 106 | `GET` with query `?type=users` 107 | 108 | #### Response 109 | 110 | `*` where `` = ` ` 111 | 112 | ### Get Messages 113 | 114 | #### Request 115 | 116 | `GET` with query `?type=messages&pubkey=&limit=` 117 | 118 | #### Response 119 | 120 | `*` in reverse chronological order where `` = `<0x00 for Inbound / 0x01 for Outbound> ` 121 | 122 | ### Get Version 123 | 124 | #### Request 125 | 126 | Unauthenticated `GET` with no query 127 | 128 | #### Response 129 | 130 | ` ` 131 | 132 | -------------------------------------------------------------------------------- /src/query.rs: -------------------------------------------------------------------------------- 1 | use ed25519_dalek::PublicKey; 2 | use failure::Error; 3 | use uuid::Uuid; 4 | 5 | const fn const_true() -> bool { 6 | true 7 | } 8 | 9 | #[derive(Clone, Debug, serde::Deserialize)] 10 | #[serde(tag = "type")] 11 | #[serde(rename_all = "camelCase")] 12 | pub enum Query { 13 | #[serde(rename_all = "camelCase")] 14 | Users { 15 | #[serde(default)] 16 | #[serde(deserialize_with = "crate::util::deser_parse")] 17 | include_recent_messages: u8, 18 | }, 19 | Login, 20 | #[serde(rename_all = "camelCase")] 21 | Messages { 22 | pubkey: String, 23 | #[serde(flatten)] 24 | limits: Limits, 25 | #[serde(default = "const_true")] 26 | mark_as_read: bool, 27 | }, 28 | #[serde(rename_all = "camelCase")] 29 | New { 30 | pubkey: String, 31 | #[serde(deserialize_with = "crate::util::deser_parse_opt")] 32 | limit: Option, 33 | }, 34 | } 35 | 36 | #[derive(Clone, Debug, serde::Deserialize)] 37 | pub struct Limits { 38 | #[serde(deserialize_with = "crate::util::deser_parse_opt")] 39 | pub limit: Option, 40 | #[serde(flatten)] 41 | pub before_after: Option, 42 | } 43 | 44 | #[derive(Clone, Debug, serde::Deserialize)] 45 | #[serde(rename_all = "lowercase")] 46 | pub enum BeforeAfter { 47 | Before(#[serde(deserialize_with = "crate::util::deser_parse")] i64), 48 | After(#[serde(deserialize_with = "crate::util::deser_parse")] i64), 49 | } 50 | 51 | pub async fn handle(q: Query) -> Result, Error> { 52 | match q { 53 | Query::Users { 54 | include_recent_messages, 55 | } => get_user_info(include_recent_messages).await, 56 | Query::Login => Ok(Vec::new()), 57 | Query::Messages { 58 | pubkey, 59 | limits, 60 | mark_as_read, 61 | } => get_messages( 62 | PublicKey::from_bytes( 63 | &base32::decode(base32::Alphabet::RFC4648 { padding: false }, &pubkey) 64 | .ok_or_else(|| failure::format_err!("invalid pubkey"))?, 65 | )?, 66 | limits, 67 | mark_as_read, 68 | ) 69 | .await 70 | .map(|(_, a)| a), 71 | Query::New { pubkey, limit } => { 72 | get_new( 73 | PublicKey::from_bytes( 74 | &base32::decode(base32::Alphabet::RFC4648 { padding: false }, &pubkey) 75 | .ok_or_else(|| failure::format_err!("invalid pubkey"))?, 76 | )?, 77 | limit, 78 | ) 79 | .await 80 | } 81 | } 82 | } 83 | 84 | pub async fn get_user_info(include_recent_messages: u8) -> Result, Error> { 85 | let dbinfo = crate::db::get_user_info().await?; 86 | let mut res = Vec::new(); 87 | for info in dbinfo { 88 | res.extend_from_slice(info.pubkey.as_bytes()); 89 | res.extend_from_slice(&u64::to_be_bytes(info.unreads as u64)); 90 | if let Some(name) = info.name { 91 | res.push(name.as_bytes().len() as u8); 92 | res.extend_from_slice(name.as_bytes()); 93 | } else { 94 | res.push(0); 95 | } 96 | if include_recent_messages > 0 { 97 | println!("including {} recent messages", include_recent_messages); 98 | let (count, messages) = get_messages( 99 | info.pubkey, 100 | Limits { 101 | before_after: None, 102 | limit: Some(include_recent_messages as usize), 103 | }, 104 | false, 105 | ) 106 | .await?; 107 | res.push(count as u8); 108 | res.extend(messages); 109 | } 110 | } 111 | Ok(res) 112 | } 113 | 114 | pub async fn get_messages( 115 | pubkey: PublicKey, 116 | limits: Limits, 117 | mark_as_read: bool, 118 | ) -> Result<(usize, Vec), Error> { 119 | let dbmsgs = crate::db::get_messages(pubkey, limits, mark_as_read).await?; 120 | let count = dbmsgs.len(); 121 | let mut res = Vec::new(); 122 | for msg in dbmsgs { 123 | if msg.inbound { 124 | res.push(1); 125 | } else { 126 | res.push(0); 127 | } 128 | res.extend_from_slice(&i64::to_be_bytes(msg.id)); 129 | res.extend_from_slice(&msg.tracking_id.unwrap_or_else(Uuid::nil).as_bytes()[..]); 130 | res.extend_from_slice(&i64::to_be_bytes(msg.time)); 131 | res.extend_from_slice(&u64::to_be_bytes(msg.content.as_bytes().len() as u64)); 132 | res.extend_from_slice(msg.content.as_bytes()); 133 | } 134 | Ok((count, res)) 135 | } 136 | 137 | pub async fn get_new(pubkey: PublicKey, limit: Option) -> Result, Error> { 138 | let dbmsgs = crate::db::get_new_messages(pubkey, limit, true).await?; 139 | let mut res = Vec::new(); 140 | for msg in dbmsgs { 141 | if msg.inbound { 142 | res.push(1); 143 | } else { 144 | res.push(0); 145 | } 146 | res.extend_from_slice(&i64::to_be_bytes(msg.id)); 147 | res.extend_from_slice(&msg.tracking_id.unwrap_or_else(Uuid::nil).as_bytes()[..]); 148 | res.extend_from_slice(&i64::to_be_bytes(msg.time)); 149 | res.extend_from_slice(&u64::to_be_bytes(msg.content.as_bytes().len() as u64)); 150 | res.extend_from_slice(msg.content.as_bytes()); 151 | } 152 | Ok(res) 153 | } 154 | -------------------------------------------------------------------------------- /src/main.rs: -------------------------------------------------------------------------------- 1 | use std::convert::Infallible; 2 | use std::net::SocketAddr; 3 | 4 | use ed25519_dalek::PublicKey; 5 | use failure::Error; 6 | use hyper::body::HttpBody; 7 | use hyper::service::{make_service_fn, service_fn}; 8 | use hyper::{Body, Method, Request, Response, Server}; 9 | use uuid::Uuid; 10 | 11 | mod db; 12 | mod delete; 13 | mod message; 14 | mod migrations; 15 | mod query; 16 | mod util; 17 | mod wire; 18 | 19 | #[derive(serde::Deserialize)] 20 | #[serde(rename_all = "kebab-case")] 21 | pub struct Config { 22 | pub password: String, 23 | pub address_private_key: String, 24 | } 25 | 26 | lazy_static::lazy_static! { 27 | pub static ref MAJOR: [u8; 8] = u64::to_be_bytes(env!("CARGO_PKG_VERSION_MAJOR").parse().unwrap()); 28 | pub static ref MINOR: [u8; 8] = u64::to_be_bytes(env!("CARGO_PKG_VERSION_MINOR").parse().unwrap()); 29 | pub static ref PATCH: [u8; 8] = u64::to_be_bytes(env!("CARGO_PKG_VERSION_PATCH").parse().unwrap()); 30 | pub static ref VERSION: [u8; 24] = { 31 | let mut version = [0; 24]; 32 | version[..8].clone_from_slice(&*MAJOR); 33 | version[8..16].clone_from_slice(&*MINOR); 34 | version[16..].clone_from_slice(&*PATCH); 35 | version 36 | }; 37 | pub static ref CONFIG: Config = serde_yaml::from_reader(std::fs::File::open("./start9/config.yaml").expect("./start9/config.yaml")).expect("./start9/config.yaml"); 38 | pub static ref PROXY: reqwest::Proxy = reqwest::Proxy::http("socks5h://embassy:9050").expect("PROXY"); 39 | pub static ref SECKEY: ed25519_dalek::ExpandedSecretKey = 40 | ed25519_dalek::ExpandedSecretKey::from_bytes( 41 | &base32::decode( 42 | base32::Alphabet::RFC4648 { padding: false }, 43 | &CONFIG.address_private_key, 44 | ).expect("TOR_KEY"), 45 | ).expect("TOR_KEY"); 46 | } 47 | 48 | async fn get_bytes(body: &mut Body) -> Result, Error> { 49 | let mut res = Vec::new(); 50 | while { 51 | if let Some(chunk) = body.data().await { 52 | res.extend_from_slice(&*chunk?); 53 | true 54 | } else { 55 | false 56 | } 57 | } {} 58 | Ok(res) 59 | } 60 | 61 | async fn handle(req: Request) -> Result, Error> { 62 | let res = handler(req).await; 63 | match &res { 64 | Ok(_) => { 65 | eprintln!("OK"); 66 | res 67 | } 68 | Err(e) => { 69 | eprintln!("ERROR: {}", e); 70 | Response::builder() 71 | .status(500) 72 | .body(format!("{}", e).into()) 73 | .map_err(From::from) 74 | } 75 | } 76 | } 77 | 78 | async fn handler(mut req: Request) -> Result, Error> { 79 | match req.method() { 80 | &Method::POST => match req.headers().get("Authorization") { 81 | Some(auth) => { 82 | if auth 83 | == &format!( 84 | "Basic {}", 85 | base64::encode(&format!("me:{}", &*CONFIG.password)) 86 | ) 87 | { 88 | let req_data = get_bytes(req.body_mut()).await?; 89 | if req_data.len() < 33 { 90 | Response::builder() 91 | .status(400) 92 | .body(Body::empty()) 93 | .map_err(From::from) 94 | } else { 95 | match req_data[0] { 96 | 0 => crate::message::send(crate::message::NewOutboundMessage { 97 | tracking_id: Some(Uuid::from_slice(&req_data[1..17])?) 98 | .filter(|a| !a.is_nil()), 99 | to: PublicKey::from_bytes(&req_data[17..49])?, 100 | time: std::time::UNIX_EPOCH 101 | .elapsed() 102 | .map(|a| a.as_secs() as i64) 103 | .unwrap_or_else(|a| a.duration().as_secs() as i64 * -1), 104 | content: String::from_utf8(req_data[49..].to_vec())?, 105 | }) 106 | .await 107 | .map(|_| Body::empty()) 108 | .map(Response::new), 109 | 1 => crate::db::save_user( 110 | PublicKey::from_bytes(&req_data[1..33])?, 111 | String::from_utf8(req_data[33..].to_vec())?, 112 | ) 113 | .await 114 | .map(|_| Body::empty()) 115 | .map(Response::new), 116 | _ => Response::builder() 117 | .status(400) 118 | .body(Body::empty()) 119 | .map_err(From::from), 120 | } 121 | } 122 | } else { 123 | Response::builder() 124 | .status(401) 125 | .body(Body::empty()) 126 | .map_err(From::from) 127 | } 128 | } 129 | _ => crate::message::receive(&get_bytes(req.body_mut()).await?) 130 | .await 131 | .map(|_| Body::empty()) 132 | .map(Response::new), 133 | }, 134 | &Method::GET => match (req.headers().get("Authorization"), req.uri().query()) { 135 | (Some(auth), Some(query)) 136 | if auth 137 | == &format!( 138 | "Basic {}", 139 | base64::encode(&format!("me:{}", &*CONFIG.password)) 140 | ) => 141 | { 142 | match serde_urlencoded::from_str(query) { 143 | Ok(q) => crate::query::handle(q) 144 | .await 145 | .map(Body::from) 146 | .map(Response::new), 147 | Err(e) => Response::builder() 148 | .status(400) 149 | .body(Body::from(format!("{}", e))) 150 | .map_err(From::from), 151 | } 152 | } 153 | (_, None) => Ok(Response::new(Body::from(&VERSION[..]))), 154 | _ => Response::builder() 155 | .status(401) 156 | .body(Body::empty()) 157 | .map_err(From::from), 158 | }, 159 | &Method::DELETE => match (req.headers().get("Authorization"), req.uri().query()) { 160 | (Some(auth), Some(query)) 161 | if auth 162 | == &format!( 163 | "Basic {}", 164 | base64::encode(&format!("me:{}", &*CONFIG.password)) 165 | ) => 166 | { 167 | match serde_urlencoded::from_str(query) { 168 | Ok(q) => crate::delete::handle(q) 169 | .await 170 | .map(|_| Body::empty()) 171 | .map(Response::new), 172 | Err(e) => Response::builder() 173 | .status(400) 174 | .body(Body::from(format!("{}", e))) 175 | .map_err(From::from), 176 | } 177 | } 178 | (_, None) => Response::builder() 179 | .status(400) 180 | .body(Body::empty()) 181 | .map_err(From::from), 182 | _ => Response::builder() 183 | .status(401) 184 | .body(Body::empty()) 185 | .map_err(From::from), 186 | }, 187 | _ => Response::builder() 188 | .status(405) 189 | .body(Body::empty()) 190 | .map_err(From::from), 191 | } 192 | } 193 | 194 | #[derive(Clone, Debug, serde::Serialize)] 195 | pub struct Metrics<'a> { 196 | version: u8, 197 | data: Data<'a>, 198 | } 199 | 200 | #[derive(Clone, Debug, serde::Serialize)] 201 | pub struct Data<'a> { 202 | password: Metric<'a>, 203 | } 204 | 205 | #[derive(Clone, Debug, serde::Serialize)] 206 | pub struct Metric<'a> { 207 | #[serde(rename = "type")] 208 | value_type: &'static str, 209 | value: &'a str, 210 | description: Option<&'static str>, 211 | copyable: bool, 212 | qr: bool, 213 | masked: bool, 214 | } 215 | 216 | #[tokio::main(worker_threads = 4)] 217 | async fn main() { 218 | println!("USING PROXY: {:?}", &*PROXY); 219 | &*CONFIG; 220 | let data = Data { 221 | password: Metric { 222 | value_type: "string", 223 | value: &CONFIG.password, 224 | description: Some("Password for authenticating to your Cups service. This password can be updated in the Cups config page."), 225 | copyable: true, 226 | qr: false, 227 | masked: true, 228 | } 229 | }; 230 | serde_yaml::to_writer( 231 | std::fs::File::create("/root/start9/.stats.yaml.tmp").unwrap(), 232 | &Metrics { version: 2, data }, 233 | ) 234 | .unwrap(); 235 | std::fs::rename("./start9/.stats.yaml.tmp", "./start9/stats.yaml").unwrap(); 236 | 237 | let mig = crate::migrations::migrate(); 238 | // Construct our SocketAddr to listen on... 239 | let addr = SocketAddr::from(([0, 0, 0, 0], 59001)); 240 | 241 | // And a MakeService to handle each connection... 242 | let make_service = make_service_fn(|_conn| async { Ok::<_, Infallible>(service_fn(handle)) }); 243 | 244 | // Then bind and serve... 245 | let server = Server::bind(&addr).serve(make_service); 246 | 247 | mig.await.expect("migration"); 248 | // And run forever... 249 | if let Err(e) = server.await { 250 | eprintln!("server error: {}", e); 251 | } 252 | } 253 | -------------------------------------------------------------------------------- /src/db.rs: -------------------------------------------------------------------------------- 1 | use ed25519_dalek::PublicKey; 2 | use failure::Error; 3 | use rusqlite::params; 4 | use rusqlite::Connection; 5 | use rusqlite::OptionalExtension; 6 | use uuid::Uuid; 7 | use failure::ResultExt; 8 | use r2d2::Pool; 9 | use r2d2_sqlite::SqliteConnectionManager; 10 | use rusqlite::OpenFlags; 11 | 12 | use crate::message::{NewInboundMessage, NewOutboundMessage}; 13 | use crate::query::BeforeAfter; 14 | use crate::query::Limits; 15 | 16 | lazy_static::lazy_static! { 17 | pub static ref POOL: Pool = { 18 | let mut flags = OpenFlags::empty(); 19 | flags.insert(OpenFlags::SQLITE_OPEN_READ_WRITE); 20 | flags.insert(OpenFlags::SQLITE_OPEN_CREATE); 21 | flags.insert(OpenFlags::SQLITE_OPEN_FULL_MUTEX); 22 | flags.insert(OpenFlags::SQLITE_OPEN_PRIVATE_CACHE); 23 | Pool::new(SqliteConnectionManager::file("messages.db").with_flags(flags).with_init(|c| c.execute_batch("PRAGMA busy_timeout = 10000;"))).expect("sqlite connection") 24 | }; 25 | } 26 | 27 | pub fn cached_exec

(conn: &Connection, q: &str, params: P) -> Result<(), Error> 28 | where 29 | P: IntoIterator + rusqlite::Params, 30 | P::Item: rusqlite::ToSql, 31 | { 32 | let mut stmt = conn.prepare_cached(q).with_context(|e| format!("{}: {}", q, e))?; 33 | stmt.execute(params).with_context(|e| format!("{}: {}", q, e))?; 34 | Ok(()) 35 | } 36 | 37 | pub fn cached_query_row(conn: & Connection, q: &str, params: P, f: F) -> Result, Error> 38 | where 39 | P: IntoIterator + rusqlite::Params, 40 | P::Item: rusqlite::ToSql, 41 | F: FnMut(&rusqlite::Row) -> Result 42 | { 43 | let mut stmt = conn.prepare_cached(q).with_context(|e| format!("{}: {}", q, e))?; 44 | let res = stmt.query_row(params, f).optional().with_context(|e| format!("{}: {}", q, e))?; 45 | Ok(res) 46 | } 47 | 48 | pub fn cached_query_map(conn: &Connection, q: &str, params: P, f: F) -> Result, Error> 49 | where 50 | P: IntoIterator + rusqlite::Params, 51 | P::Item: rusqlite::ToSql, 52 | F: FnMut(&rusqlite::Row) -> Result 53 | { 54 | let mut stmt = conn.prepare_cached(q).with_context(|e| format!("{}: {}", q, e))?; 55 | let res = stmt.query_map(params, f).with_context(|e| format!("{}: {}", q, e))?; 56 | res.map(|r| r.with_context(|e| format!("{}: {}", q, e)).map_err(From::from)).collect() 57 | } 58 | 59 | pub async fn save_in_message(message: NewInboundMessage) -> Result<(), Error> { 60 | tokio::task::spawn_blocking(move || { 61 | let conn = POOL.get()?; 62 | cached_exec( 63 | &*conn, 64 | "INSERT INTO messages (user_id, inbound, time, content) VALUES (?1, true, ?2, ?3)", 65 | params![ 66 | &message.from.as_bytes()[..], 67 | message.time, 68 | message.content 69 | ], 70 | )?; 71 | Ok::<_, Error>(()) 72 | }) 73 | .await??; 74 | Ok(()) 75 | } 76 | 77 | pub async fn save_out_message(message: NewOutboundMessage) -> Result<(), Error> { 78 | tokio::task::spawn_blocking(move || { 79 | let conn = POOL.get()?; 80 | cached_exec( 81 | &*conn, 82 | "INSERT INTO messages (tracking_id, user_id, inbound, time, content, read) VALUES (?1, ?2, false, ?3, ?4, true)", 83 | params![message.tracking_id, &message.to.as_bytes()[..], message.time, message.content], 84 | )?; 85 | Ok::<_, Error>(()) 86 | }) 87 | .await??; 88 | Ok(()) 89 | } 90 | 91 | pub async fn save_user(pubkey: PublicKey, name: String) -> Result<(), Error> { 92 | tokio::task::spawn_blocking(move || { 93 | let conn = POOL.get()?; 94 | cached_exec( 95 | &*conn, 96 | "INSERT INTO users (id, name) VALUES (?1, ?2) ON CONFLICT(id) DO UPDATE SET name = excluded.name", 97 | params![&pubkey.as_bytes()[..], name], 98 | )?; 99 | Ok::<_, Error>(()) 100 | }) 101 | .await??; 102 | Ok(()) 103 | } 104 | 105 | pub async fn del_user(pubkey: PublicKey) -> Result<(), Error> { 106 | let res = tokio::task::spawn_blocking(move || { 107 | let mut gconn = POOL.get()?; 108 | let conn = gconn.transaction()?; 109 | cached_exec( 110 | &*conn, 111 | "DELETE FROM users WHERE id = ?1", 112 | params![&pubkey.as_bytes()[..]], 113 | )?; 114 | cached_exec( 115 | &*conn, 116 | "DELETE FROM messages WHERE user_id = ?1", 117 | params![&pubkey.as_bytes()[..]], 118 | )?; 119 | conn.commit()?; 120 | Ok::<_, Error>(()) 121 | }) 122 | .await??; 123 | Ok(res) 124 | } 125 | 126 | #[derive(Clone, Debug)] 127 | pub struct UserInfo { 128 | pub pubkey: PublicKey, 129 | pub name: Option, 130 | pub unreads: i64, 131 | } 132 | 133 | pub async fn get_user_info() -> Result, Error> { 134 | let res = tokio::task::spawn_blocking(move || { 135 | let conn = POOL.get()?; 136 | let mut stmt = conn.prepare_cached( 137 | "SELECT 138 | messages.user_id, 139 | users.name, 140 | SUM(CASE WHEN messages.read THEN 0 ELSE 1 END) 141 | FROM messages 142 | LEFT JOIN users 143 | ON messages.user_id = users.id 144 | GROUP BY messages.user_id, users.name 145 | UNION ALL 146 | SELECT 147 | users.id, 148 | users.name, 149 | count(messages.id) 150 | FROM users 151 | LEFT JOIN messages 152 | ON messages.user_id = users.id 153 | WHERE messages.user_id IS NULL 154 | GROUP BY users.id, users.name", 155 | )?; 156 | let res = stmt 157 | .query_map(params![], |row| { 158 | let uid: Vec = row.get(0)?; 159 | Ok(UserInfo { 160 | pubkey: PublicKey::from_bytes(&uid).map_err(|e| { 161 | rusqlite::Error::FromSqlConversionFailure( 162 | 0, 163 | rusqlite::types::Type::Blob, 164 | Box::new(e), 165 | ) 166 | })?, 167 | name: row.get(1)?, 168 | unreads: row.get(2)?, 169 | }) 170 | })? 171 | .collect::>()?; 172 | Ok::<_, Error>(res) 173 | }) 174 | .await??; 175 | Ok(res) 176 | } 177 | 178 | #[derive(Clone, Debug)] 179 | pub struct Message { 180 | pub id: i64, 181 | pub tracking_id: Option, 182 | pub time: i64, 183 | pub inbound: bool, 184 | pub content: String, 185 | } 186 | 187 | pub async fn get_messages( 188 | pubkey: PublicKey, 189 | limits: Limits, 190 | mark_as_read: bool, 191 | ) -> Result, Error> { 192 | let res = tokio::task::spawn_blocking(move || { 193 | let mut gconn = POOL.get()?; 194 | let conn = gconn.transaction()?; 195 | if mark_as_read { 196 | match (&limits.before_after, &limits.limit) { 197 | (Some(BeforeAfter::Before(before)), None) => cached_exec( 198 | &*conn, 199 | "UPDATE messages SET read = true WHERE user_id = ?1 AND id IN (SELECT id FROM messages WHERE user_id = ?1 AND id < ?2 ORDER BY id DESC)", 200 | params![&pubkey.as_bytes()[..], before], 201 | )?, 202 | (Some(BeforeAfter::Before(before)), Some(limit)) => cached_exec( 203 | &*conn, 204 | "UPDATE messages SET read = true WHERE user_id = ?1 AND id IN (SELECT id FROM messages WHERE user_id = ?1 AND id < ?2 ORDER BY id DESC LIMIT ?3)", 205 | params![&pubkey.as_bytes()[..], before, *limit as i64], 206 | )?, 207 | (Some(BeforeAfter::After(after)), None) => cached_exec( 208 | &*conn, 209 | "UPDATE messages SET read = true WHERE user_id = ?1 AND id IN (SELECT id FROM messages WHERE user_id = ?1 AND id > ?2 ORDER BY id ASC)", 210 | params![&pubkey.as_bytes()[..], after], 211 | )?, 212 | (Some(BeforeAfter::After(after)), Some(limit)) => cached_exec( 213 | &*conn, 214 | "UPDATE messages SET read = true WHERE user_id = ?1 AND id IN (SELECT id FROM messages WHERE user_id = ?1 AND id > ?2 ORDER BY id ASC LIMIT ?3)", 215 | params![&pubkey.as_bytes()[..], after, *limit as i64], 216 | )?, 217 | (None, None) => cached_exec( 218 | &*conn, 219 | "UPDATE messages SET read = true WHERE user_id = ?1 AND id IN (SELECT id FROM messages WHERE user_id = ?1 ORDER BY id DESC)", 220 | params![&pubkey.as_bytes()[..]], 221 | )?, 222 | (None, Some(limit)) => cached_exec( 223 | &*conn, 224 | "UPDATE messages SET read = true WHERE user_id = ?1 AND id IN (SELECT id FROM messages WHERE user_id = ?1 ORDER BY id DESC LIMIT ?2)", 225 | params![&pubkey.as_bytes()[..], *limit as i64], 226 | )?, 227 | }; 228 | } 229 | let mapper = |row: &rusqlite::Row| { 230 | Ok(Message { 231 | id: row.get(0)?, 232 | tracking_id: row.get(1)?, 233 | time: row.get(2)?, 234 | inbound: row.get(3)?, 235 | content: row.get(4)?, 236 | }) 237 | }; 238 | let res = match (&limits.before_after, &limits.limit) { 239 | (Some(BeforeAfter::Before(before)), None) => cached_query_map( 240 | &*conn, 241 | "SELECT id, tracking_id, time, inbound, content FROM messages WHERE user_id = ?1 AND id < ?2 ORDER BY id DESC", 242 | params![&pubkey.as_bytes()[..], before], 243 | mapper, 244 | )?, 245 | (Some(BeforeAfter::Before(before)), Some(limit)) => cached_query_map( 246 | &*conn, 247 | "SELECT id, tracking_id, time, inbound, content FROM messages WHERE user_id = ?1 AND id < ?2 ORDER BY id DESC LIMIT ?3", 248 | params![&pubkey.as_bytes()[..], before, *limit as i64], 249 | mapper, 250 | )?, 251 | (Some(BeforeAfter::After(after)), None) => cached_query_map( 252 | &*conn, 253 | "SELECT id, tracking_id, time, inbound, content FROM messages WHERE user_id = ?1 AND id > ?2 ORDER BY id ASC", 254 | params![&pubkey.as_bytes()[..], after], 255 | mapper, 256 | )?, 257 | (Some(BeforeAfter::After(after)), Some(limit)) => cached_query_map( 258 | &*conn, 259 | "SELECT id, tracking_id, time, inbound, content FROM messages WHERE user_id = ?1 AND id > ?2 ORDER BY id ASC LIMIT ?3", 260 | params![&pubkey.as_bytes()[..], after, *limit as i64], 261 | mapper, 262 | )?, 263 | (None, None) => cached_query_map( 264 | &*conn, 265 | "SELECT id, tracking_id, time, inbound, content FROM messages WHERE user_id = ?1 ORDER BY id DESC", 266 | params![&pubkey.as_bytes()[..]], 267 | mapper, 268 | )?, 269 | (None, Some(limit)) => cached_query_map( 270 | &*conn, 271 | "SELECT id, tracking_id, time, inbound, content FROM messages WHERE user_id = ?1 ORDER BY id DESC LIMIT ?2", 272 | params![&pubkey.as_bytes()[..], *limit as i64], 273 | mapper, 274 | )?, 275 | }; 276 | conn.commit()?; 277 | Ok::<_, Error>(res) 278 | }) 279 | .await??; 280 | Ok(res) 281 | } 282 | 283 | pub async fn get_new_messages( 284 | pubkey: PublicKey, 285 | limit: Option, 286 | mark_as_read: bool, 287 | ) -> Result, Error> { 288 | let res = tokio::task::spawn_blocking(move || { 289 | let mut gconn = POOL.get()?; 290 | let conn = gconn.transaction()?; 291 | let id: Option = cached_query_row( 292 | &*conn, 293 | "SELECT id FROM messages WHERE user_id = ?1 AND read = false ORDER BY id ASC LIMIT 1", 294 | params![&pubkey.as_bytes()[..]], 295 | |row| row.get(0), 296 | )?; 297 | let id = if let Some(id) = id { 298 | id 299 | } else { 300 | return Ok(Vec::new()); 301 | }; 302 | if mark_as_read { 303 | if let Some(limit) = limit { 304 | cached_exec( 305 | &*conn, 306 | "UPDATE messages SET read = true WHERE user_id = ?1 AND id IN (SELECT id FROM messages WHERE user_id = ?1 AND id >= ?2 ORDER BY id ASC LIMIT ?3)", 307 | params![&pubkey.as_bytes()[..], id, limit as i64] 308 | )?; 309 | } else { 310 | cached_exec( 311 | &*conn, 312 | "UPDATE messages SET read = true WHERE user_id = ?1 AND id IN (SELECT id FROM messages WHERE user_id = ?1 AND id >= ?2 ORDER BY id ASC)", 313 | params![&pubkey.as_bytes()[..], id] 314 | )?; 315 | } 316 | } 317 | let mapper = |row: &rusqlite::Row| { 318 | Ok(Message { 319 | id: row.get(0)?, 320 | tracking_id: row.get(1)?, 321 | time: row.get(2)?, 322 | inbound: row.get(3)?, 323 | content: row.get(4)?, 324 | }) 325 | }; 326 | let res = if let Some(limit) = limit { 327 | cached_query_map( 328 | &*conn, 329 | "SELECT id, tracking_id, time, inbound, content FROM messages WHERE user_id = ?1 AND id >= ?2 ORDER BY id ASC LIMIT ?3", 330 | params![&pubkey.as_bytes()[..], id, limit as i64], 331 | mapper 332 | )? 333 | } else { 334 | cached_query_map( 335 | &*conn, 336 | "SELECT id, tracking_id, time, inbound, content FROM messages WHERE user_id = ?1 AND id >= ?2 ORDER BY id ASC", 337 | params![&pubkey.as_bytes()[..], id], 338 | mapper 339 | )? 340 | }; 341 | conn.commit()?; 342 | Ok::<_, Error>(res) 343 | }) 344 | .await??; 345 | Ok(res) 346 | } 347 | -------------------------------------------------------------------------------- /Cargo.lock: -------------------------------------------------------------------------------- 1 | # This file is automatically @generated by Cargo. 2 | # It is not intended for manual editing. 3 | version = 3 4 | 5 | [[package]] 6 | name = "addr2line" 7 | version = "0.17.0" 8 | source = "registry+https://github.com/rust-lang/crates.io-index" 9 | checksum = "b9ecd88a8c8378ca913a680cd98f0f13ac67383d35993f86c90a70e3f137816b" 10 | dependencies = [ 11 | "gimli", 12 | ] 13 | 14 | [[package]] 15 | name = "adler" 16 | version = "1.0.2" 17 | source = "registry+https://github.com/rust-lang/crates.io-index" 18 | checksum = "f26201604c87b1e01bd3d98f8d5d9a8fcbb815e8cedb41ffccbeb4bf593a35fe" 19 | 20 | [[package]] 21 | name = "ahash" 22 | version = "0.7.6" 23 | source = "registry+https://github.com/rust-lang/crates.io-index" 24 | checksum = "fcb51a0695d8f838b1ee009b3fbf66bda078cd64590202a864a8f3e8c4315c47" 25 | dependencies = [ 26 | "getrandom 0.2.8", 27 | "once_cell", 28 | "version_check", 29 | ] 30 | 31 | [[package]] 32 | name = "autocfg" 33 | version = "1.1.0" 34 | source = "registry+https://github.com/rust-lang/crates.io-index" 35 | checksum = "d468802bab17cbc0cc575e9b053f41e72aa36bfa6b7f55e3529ffa43161b97fa" 36 | 37 | [[package]] 38 | name = "backtrace" 39 | version = "0.3.66" 40 | source = "registry+https://github.com/rust-lang/crates.io-index" 41 | checksum = "cab84319d616cfb654d03394f38ab7e6f0919e181b1b57e1fd15e7fb4077d9a7" 42 | dependencies = [ 43 | "addr2line", 44 | "cc", 45 | "cfg-if", 46 | "libc", 47 | "miniz_oxide", 48 | "object", 49 | "rustc-demangle", 50 | ] 51 | 52 | [[package]] 53 | name = "base32" 54 | version = "0.4.0" 55 | source = "registry+https://github.com/rust-lang/crates.io-index" 56 | checksum = "23ce669cd6c8588f79e15cf450314f9638f967fc5770ff1c7c1deb0925ea7cfa" 57 | 58 | [[package]] 59 | name = "base64" 60 | version = "0.13.1" 61 | source = "registry+https://github.com/rust-lang/crates.io-index" 62 | checksum = "9e1b586273c5702936fe7b7d6896644d8be71e6314cfe09d3167c95f712589e8" 63 | 64 | [[package]] 65 | name = "bitflags" 66 | version = "1.3.2" 67 | source = "registry+https://github.com/rust-lang/crates.io-index" 68 | checksum = "bef38d45163c2f1dde094a7dfd33ccf595c92905c8f8f4fdc18d06fb1037718a" 69 | 70 | [[package]] 71 | name = "block-buffer" 72 | version = "0.9.0" 73 | source = "registry+https://github.com/rust-lang/crates.io-index" 74 | checksum = "4152116fd6e9dadb291ae18fc1ec3575ed6d84c29642d97890f4b4a3417297e4" 75 | dependencies = [ 76 | "block-padding", 77 | "generic-array", 78 | ] 79 | 80 | [[package]] 81 | name = "block-padding" 82 | version = "0.2.1" 83 | source = "registry+https://github.com/rust-lang/crates.io-index" 84 | checksum = "8d696c370c750c948ada61c69a0ee2cbbb9c50b1019ddb86d9317157a99c2cae" 85 | 86 | [[package]] 87 | name = "bumpalo" 88 | version = "3.11.1" 89 | source = "registry+https://github.com/rust-lang/crates.io-index" 90 | checksum = "572f695136211188308f16ad2ca5c851a712c464060ae6974944458eb83880ba" 91 | 92 | [[package]] 93 | name = "byteorder" 94 | version = "1.4.3" 95 | source = "registry+https://github.com/rust-lang/crates.io-index" 96 | checksum = "14c189c53d098945499cdfa7ecc63567cf3886b3332b312a5b4585d8d3a6a610" 97 | 98 | [[package]] 99 | name = "bytes" 100 | version = "1.3.0" 101 | source = "registry+https://github.com/rust-lang/crates.io-index" 102 | checksum = "dfb24e866b15a1af2a1b663f10c6b6b8f397a84aadb828f12e5b289ec23a3a3c" 103 | 104 | [[package]] 105 | name = "cc" 106 | version = "1.0.77" 107 | source = "registry+https://github.com/rust-lang/crates.io-index" 108 | checksum = "e9f73505338f7d905b19d18738976aae232eb46b8efc15554ffc56deb5d9ebe4" 109 | 110 | [[package]] 111 | name = "cfg-if" 112 | version = "1.0.0" 113 | source = "registry+https://github.com/rust-lang/crates.io-index" 114 | checksum = "baf1de4339761588bc0619e3cbc0120ee582ebb74b53b4efbf79117bd2da40fd" 115 | 116 | [[package]] 117 | name = "core-foundation" 118 | version = "0.9.3" 119 | source = "registry+https://github.com/rust-lang/crates.io-index" 120 | checksum = "194a7a9e6de53fa55116934067c844d9d749312f75c6f6d0980e8c252f8c2146" 121 | dependencies = [ 122 | "core-foundation-sys", 123 | "libc", 124 | ] 125 | 126 | [[package]] 127 | name = "core-foundation-sys" 128 | version = "0.8.3" 129 | source = "registry+https://github.com/rust-lang/crates.io-index" 130 | checksum = "5827cebf4670468b8772dd191856768aedcb1b0278a04f989f7766351917b9dc" 131 | 132 | [[package]] 133 | name = "cpufeatures" 134 | version = "0.2.5" 135 | source = "registry+https://github.com/rust-lang/crates.io-index" 136 | checksum = "28d997bd5e24a5928dd43e46dc529867e207907fe0b239c3477d924f7f2ca320" 137 | dependencies = [ 138 | "libc", 139 | ] 140 | 141 | [[package]] 142 | name = "cups" 143 | version = "0.3.8" 144 | dependencies = [ 145 | "base32", 146 | "base64", 147 | "ed25519-dalek", 148 | "failure", 149 | "futures", 150 | "hyper", 151 | "hyper-tls", 152 | "lazy_static", 153 | "openssl", 154 | "parking_lot 0.11.2", 155 | "r2d2", 156 | "r2d2_sqlite", 157 | "reqwest", 158 | "rusqlite", 159 | "serde", 160 | "serde_urlencoded", 161 | "serde_yaml", 162 | "sha3", 163 | "tokio", 164 | "uuid", 165 | ] 166 | 167 | [[package]] 168 | name = "curve25519-dalek" 169 | version = "3.2.1" 170 | source = "registry+https://github.com/rust-lang/crates.io-index" 171 | checksum = "90f9d052967f590a76e62eb387bd0bbb1b000182c3cefe5364db6b7211651bc0" 172 | dependencies = [ 173 | "byteorder", 174 | "digest", 175 | "rand_core", 176 | "subtle", 177 | "zeroize", 178 | ] 179 | 180 | [[package]] 181 | name = "digest" 182 | version = "0.9.0" 183 | source = "registry+https://github.com/rust-lang/crates.io-index" 184 | checksum = "d3dd60d1080a57a05ab032377049e0591415d2b31afd7028356dbf3cc6dcb066" 185 | dependencies = [ 186 | "generic-array", 187 | ] 188 | 189 | [[package]] 190 | name = "ed25519" 191 | version = "1.5.2" 192 | source = "registry+https://github.com/rust-lang/crates.io-index" 193 | checksum = "1e9c280362032ea4203659fc489832d0204ef09f247a0506f170dafcac08c369" 194 | dependencies = [ 195 | "signature", 196 | ] 197 | 198 | [[package]] 199 | name = "ed25519-dalek" 200 | version = "1.0.1" 201 | source = "registry+https://github.com/rust-lang/crates.io-index" 202 | checksum = "c762bae6dcaf24c4c84667b8579785430908723d5c889f469d76a41d59cc7a9d" 203 | dependencies = [ 204 | "curve25519-dalek", 205 | "ed25519", 206 | "rand", 207 | "serde", 208 | "sha2", 209 | "zeroize", 210 | ] 211 | 212 | [[package]] 213 | name = "either" 214 | version = "1.8.0" 215 | source = "registry+https://github.com/rust-lang/crates.io-index" 216 | checksum = "90e5c1c8368803113bf0c9584fc495a58b86dc8a29edbf8fe877d21d9507e797" 217 | 218 | [[package]] 219 | name = "encoding_rs" 220 | version = "0.8.31" 221 | source = "registry+https://github.com/rust-lang/crates.io-index" 222 | checksum = "9852635589dc9f9ea1b6fe9f05b50ef208c85c834a562f0c6abb1c475736ec2b" 223 | dependencies = [ 224 | "cfg-if", 225 | ] 226 | 227 | [[package]] 228 | name = "failure" 229 | version = "0.1.8" 230 | source = "registry+https://github.com/rust-lang/crates.io-index" 231 | checksum = "d32e9bd16cc02eae7db7ef620b392808b89f6a5e16bb3497d159c6b92a0f4f86" 232 | dependencies = [ 233 | "backtrace", 234 | "failure_derive", 235 | ] 236 | 237 | [[package]] 238 | name = "failure_derive" 239 | version = "0.1.8" 240 | source = "registry+https://github.com/rust-lang/crates.io-index" 241 | checksum = "aa4da3c766cd7a0db8242e326e9e4e081edd567072893ed320008189715366a4" 242 | dependencies = [ 243 | "proc-macro2", 244 | "quote", 245 | "syn", 246 | "synstructure", 247 | ] 248 | 249 | [[package]] 250 | name = "fallible-iterator" 251 | version = "0.2.0" 252 | source = "registry+https://github.com/rust-lang/crates.io-index" 253 | checksum = "4443176a9f2c162692bd3d352d745ef9413eec5782a80d8fd6f8a1ac692a07f7" 254 | 255 | [[package]] 256 | name = "fallible-streaming-iterator" 257 | version = "0.1.9" 258 | source = "registry+https://github.com/rust-lang/crates.io-index" 259 | checksum = "7360491ce676a36bf9bb3c56c1aa791658183a54d2744120f27285738d90465a" 260 | 261 | [[package]] 262 | name = "fastrand" 263 | version = "1.8.0" 264 | source = "registry+https://github.com/rust-lang/crates.io-index" 265 | checksum = "a7a407cfaa3385c4ae6b23e84623d48c2798d06e3e6a1878f7f59f17b3f86499" 266 | dependencies = [ 267 | "instant", 268 | ] 269 | 270 | [[package]] 271 | name = "fnv" 272 | version = "1.0.7" 273 | source = "registry+https://github.com/rust-lang/crates.io-index" 274 | checksum = "3f9eec918d3f24069decb9af1554cad7c880e2da24a9afd88aca000531ab82c1" 275 | 276 | [[package]] 277 | name = "foreign-types" 278 | version = "0.3.2" 279 | source = "registry+https://github.com/rust-lang/crates.io-index" 280 | checksum = "f6f339eb8adc052cd2ca78910fda869aefa38d22d5cb648e6485e4d3fc06f3b1" 281 | dependencies = [ 282 | "foreign-types-shared", 283 | ] 284 | 285 | [[package]] 286 | name = "foreign-types-shared" 287 | version = "0.1.1" 288 | source = "registry+https://github.com/rust-lang/crates.io-index" 289 | checksum = "00b0228411908ca8685dba7fc2cdd70ec9990a6e753e89b6ac91a84c40fbaf4b" 290 | 291 | [[package]] 292 | name = "form_urlencoded" 293 | version = "1.1.0" 294 | source = "registry+https://github.com/rust-lang/crates.io-index" 295 | checksum = "a9c384f161156f5260c24a097c56119f9be8c798586aecc13afbcbe7b7e26bf8" 296 | dependencies = [ 297 | "percent-encoding", 298 | ] 299 | 300 | [[package]] 301 | name = "futures" 302 | version = "0.3.25" 303 | source = "registry+https://github.com/rust-lang/crates.io-index" 304 | checksum = "38390104763dc37a5145a53c29c63c1290b5d316d6086ec32c293f6736051bb0" 305 | dependencies = [ 306 | "futures-channel", 307 | "futures-core", 308 | "futures-executor", 309 | "futures-io", 310 | "futures-sink", 311 | "futures-task", 312 | "futures-util", 313 | ] 314 | 315 | [[package]] 316 | name = "futures-channel" 317 | version = "0.3.25" 318 | source = "registry+https://github.com/rust-lang/crates.io-index" 319 | checksum = "52ba265a92256105f45b719605a571ffe2d1f0fea3807304b522c1d778f79eed" 320 | dependencies = [ 321 | "futures-core", 322 | "futures-sink", 323 | ] 324 | 325 | [[package]] 326 | name = "futures-core" 327 | version = "0.3.25" 328 | source = "registry+https://github.com/rust-lang/crates.io-index" 329 | checksum = "04909a7a7e4633ae6c4a9ab280aeb86da1236243a77b694a49eacd659a4bd3ac" 330 | 331 | [[package]] 332 | name = "futures-executor" 333 | version = "0.3.25" 334 | source = "registry+https://github.com/rust-lang/crates.io-index" 335 | checksum = "7acc85df6714c176ab5edf386123fafe217be88c0840ec11f199441134a074e2" 336 | dependencies = [ 337 | "futures-core", 338 | "futures-task", 339 | "futures-util", 340 | ] 341 | 342 | [[package]] 343 | name = "futures-io" 344 | version = "0.3.25" 345 | source = "registry+https://github.com/rust-lang/crates.io-index" 346 | checksum = "00f5fb52a06bdcadeb54e8d3671f8888a39697dcb0b81b23b55174030427f4eb" 347 | 348 | [[package]] 349 | name = "futures-macro" 350 | version = "0.3.25" 351 | source = "registry+https://github.com/rust-lang/crates.io-index" 352 | checksum = "bdfb8ce053d86b91919aad980c220b1fb8401a9394410e1c289ed7e66b61835d" 353 | dependencies = [ 354 | "proc-macro2", 355 | "quote", 356 | "syn", 357 | ] 358 | 359 | [[package]] 360 | name = "futures-sink" 361 | version = "0.3.25" 362 | source = "registry+https://github.com/rust-lang/crates.io-index" 363 | checksum = "39c15cf1a4aa79df40f1bb462fb39676d0ad9e366c2a33b590d7c66f4f81fcf9" 364 | 365 | [[package]] 366 | name = "futures-task" 367 | version = "0.3.25" 368 | source = "registry+https://github.com/rust-lang/crates.io-index" 369 | checksum = "2ffb393ac5d9a6eaa9d3fdf37ae2776656b706e200c8e16b1bdb227f5198e6ea" 370 | 371 | [[package]] 372 | name = "futures-util" 373 | version = "0.3.25" 374 | source = "registry+https://github.com/rust-lang/crates.io-index" 375 | checksum = "197676987abd2f9cadff84926f410af1c183608d36641465df73ae8211dc65d6" 376 | dependencies = [ 377 | "futures-channel", 378 | "futures-core", 379 | "futures-io", 380 | "futures-macro", 381 | "futures-sink", 382 | "futures-task", 383 | "memchr", 384 | "pin-project-lite", 385 | "pin-utils", 386 | "slab", 387 | ] 388 | 389 | [[package]] 390 | name = "generic-array" 391 | version = "0.14.6" 392 | source = "registry+https://github.com/rust-lang/crates.io-index" 393 | checksum = "bff49e947297f3312447abdca79f45f4738097cc82b06e72054d2223f601f1b9" 394 | dependencies = [ 395 | "typenum", 396 | "version_check", 397 | ] 398 | 399 | [[package]] 400 | name = "getrandom" 401 | version = "0.1.16" 402 | source = "registry+https://github.com/rust-lang/crates.io-index" 403 | checksum = "8fc3cb4d91f53b50155bdcfd23f6a4c39ae1969c2ae85982b135750cccaf5fce" 404 | dependencies = [ 405 | "cfg-if", 406 | "libc", 407 | "wasi 0.9.0+wasi-snapshot-preview1", 408 | ] 409 | 410 | [[package]] 411 | name = "getrandom" 412 | version = "0.2.8" 413 | source = "registry+https://github.com/rust-lang/crates.io-index" 414 | checksum = "c05aeb6a22b8f62540c194aac980f2115af067bfe15a0734d7277a768d396b31" 415 | dependencies = [ 416 | "cfg-if", 417 | "libc", 418 | "wasi 0.11.0+wasi-snapshot-preview1", 419 | ] 420 | 421 | [[package]] 422 | name = "gimli" 423 | version = "0.26.2" 424 | source = "registry+https://github.com/rust-lang/crates.io-index" 425 | checksum = "22030e2c5a68ec659fde1e949a745124b48e6fa8b045b7ed5bd1fe4ccc5c4e5d" 426 | 427 | [[package]] 428 | name = "h2" 429 | version = "0.3.15" 430 | source = "registry+https://github.com/rust-lang/crates.io-index" 431 | checksum = "5f9f29bc9dda355256b2916cf526ab02ce0aeaaaf2bad60d65ef3f12f11dd0f4" 432 | dependencies = [ 433 | "bytes", 434 | "fnv", 435 | "futures-core", 436 | "futures-sink", 437 | "futures-util", 438 | "http", 439 | "indexmap", 440 | "slab", 441 | "tokio", 442 | "tokio-util", 443 | "tracing", 444 | ] 445 | 446 | [[package]] 447 | name = "hashbrown" 448 | version = "0.11.2" 449 | source = "registry+https://github.com/rust-lang/crates.io-index" 450 | checksum = "ab5ef0d4909ef3724cc8cce6ccc8572c5c817592e9285f5464f8e86f8bd3726e" 451 | dependencies = [ 452 | "ahash", 453 | ] 454 | 455 | [[package]] 456 | name = "hashbrown" 457 | version = "0.12.3" 458 | source = "registry+https://github.com/rust-lang/crates.io-index" 459 | checksum = "8a9ee70c43aaf417c914396645a0fa852624801b24ebb7ae78fe8272889ac888" 460 | 461 | [[package]] 462 | name = "hashlink" 463 | version = "0.7.0" 464 | source = "registry+https://github.com/rust-lang/crates.io-index" 465 | checksum = "7249a3129cbc1ffccd74857f81464a323a152173cdb134e0fd81bc803b29facf" 466 | dependencies = [ 467 | "hashbrown 0.11.2", 468 | ] 469 | 470 | [[package]] 471 | name = "hermit-abi" 472 | version = "0.1.19" 473 | source = "registry+https://github.com/rust-lang/crates.io-index" 474 | checksum = "62b467343b94ba476dcb2500d242dadbb39557df889310ac77c5d99100aaac33" 475 | dependencies = [ 476 | "libc", 477 | ] 478 | 479 | [[package]] 480 | name = "http" 481 | version = "0.2.8" 482 | source = "registry+https://github.com/rust-lang/crates.io-index" 483 | checksum = "75f43d41e26995c17e71ee126451dd3941010b0514a81a9d11f3b341debc2399" 484 | dependencies = [ 485 | "bytes", 486 | "fnv", 487 | "itoa", 488 | ] 489 | 490 | [[package]] 491 | name = "http-body" 492 | version = "0.4.5" 493 | source = "registry+https://github.com/rust-lang/crates.io-index" 494 | checksum = "d5f38f16d184e36f2408a55281cd658ecbd3ca05cce6d6510a176eca393e26d1" 495 | dependencies = [ 496 | "bytes", 497 | "http", 498 | "pin-project-lite", 499 | ] 500 | 501 | [[package]] 502 | name = "httparse" 503 | version = "1.8.0" 504 | source = "registry+https://github.com/rust-lang/crates.io-index" 505 | checksum = "d897f394bad6a705d5f4104762e116a75639e470d80901eed05a860a95cb1904" 506 | 507 | [[package]] 508 | name = "httpdate" 509 | version = "1.0.2" 510 | source = "registry+https://github.com/rust-lang/crates.io-index" 511 | checksum = "c4a1e36c821dbe04574f602848a19f742f4fb3c98d40449f11bcad18d6b17421" 512 | 513 | [[package]] 514 | name = "hyper" 515 | version = "0.14.23" 516 | source = "registry+https://github.com/rust-lang/crates.io-index" 517 | checksum = "034711faac9d2166cb1baf1a2fb0b60b1f277f8492fd72176c17f3515e1abd3c" 518 | dependencies = [ 519 | "bytes", 520 | "futures-channel", 521 | "futures-core", 522 | "futures-util", 523 | "h2", 524 | "http", 525 | "http-body", 526 | "httparse", 527 | "httpdate", 528 | "itoa", 529 | "pin-project-lite", 530 | "socket2", 531 | "tokio", 532 | "tower-service", 533 | "tracing", 534 | "want", 535 | ] 536 | 537 | [[package]] 538 | name = "hyper-tls" 539 | version = "0.5.0" 540 | source = "registry+https://github.com/rust-lang/crates.io-index" 541 | checksum = "d6183ddfa99b85da61a140bea0efc93fdf56ceaa041b37d553518030827f9905" 542 | dependencies = [ 543 | "bytes", 544 | "hyper", 545 | "native-tls", 546 | "tokio", 547 | "tokio-native-tls", 548 | ] 549 | 550 | [[package]] 551 | name = "idna" 552 | version = "0.3.0" 553 | source = "registry+https://github.com/rust-lang/crates.io-index" 554 | checksum = "e14ddfc70884202db2244c223200c204c2bda1bc6e0998d11b5e024d657209e6" 555 | dependencies = [ 556 | "unicode-bidi", 557 | "unicode-normalization", 558 | ] 559 | 560 | [[package]] 561 | name = "indexmap" 562 | version = "1.9.2" 563 | source = "registry+https://github.com/rust-lang/crates.io-index" 564 | checksum = "1885e79c1fc4b10f0e172c475f458b7f7b93061064d98c3293e98c5ba0c8b399" 565 | dependencies = [ 566 | "autocfg", 567 | "hashbrown 0.12.3", 568 | ] 569 | 570 | [[package]] 571 | name = "instant" 572 | version = "0.1.12" 573 | source = "registry+https://github.com/rust-lang/crates.io-index" 574 | checksum = "7a5bbe824c507c5da5956355e86a746d82e0e1464f65d862cc5e71da70e94b2c" 575 | dependencies = [ 576 | "cfg-if", 577 | ] 578 | 579 | [[package]] 580 | name = "ipnet" 581 | version = "2.5.1" 582 | source = "registry+https://github.com/rust-lang/crates.io-index" 583 | checksum = "f88c5561171189e69df9d98bcf18fd5f9558300f7ea7b801eb8a0fd748bd8745" 584 | 585 | [[package]] 586 | name = "itoa" 587 | version = "1.0.4" 588 | source = "registry+https://github.com/rust-lang/crates.io-index" 589 | checksum = "4217ad341ebadf8d8e724e264f13e593e0648f5b3e94b3896a5df283be015ecc" 590 | 591 | [[package]] 592 | name = "js-sys" 593 | version = "0.3.60" 594 | source = "registry+https://github.com/rust-lang/crates.io-index" 595 | checksum = "49409df3e3bf0856b916e2ceaca09ee28e6871cf7d9ce97a692cacfdb2a25a47" 596 | dependencies = [ 597 | "wasm-bindgen", 598 | ] 599 | 600 | [[package]] 601 | name = "keccak" 602 | version = "0.1.3" 603 | source = "registry+https://github.com/rust-lang/crates.io-index" 604 | checksum = "3afef3b6eff9ce9d8ff9b3601125eec7f0c8cbac7abd14f355d053fa56c98768" 605 | dependencies = [ 606 | "cpufeatures", 607 | ] 608 | 609 | [[package]] 610 | name = "lazy_static" 611 | version = "1.4.0" 612 | source = "registry+https://github.com/rust-lang/crates.io-index" 613 | checksum = "e2abad23fbc42b3700f2f279844dc832adb2b2eb069b2df918f455c4e18cc646" 614 | 615 | [[package]] 616 | name = "libc" 617 | version = "0.2.137" 618 | source = "registry+https://github.com/rust-lang/crates.io-index" 619 | checksum = "fc7fcc620a3bff7cdd7a365be3376c97191aeaccc2a603e600951e452615bf89" 620 | 621 | [[package]] 622 | name = "libsqlite3-sys" 623 | version = "0.23.2" 624 | source = "registry+https://github.com/rust-lang/crates.io-index" 625 | checksum = "d2cafc7c74096c336d9d27145f7ebd4f4b6f95ba16aa5a282387267e6925cb58" 626 | dependencies = [ 627 | "cc", 628 | "pkg-config", 629 | "vcpkg", 630 | ] 631 | 632 | [[package]] 633 | name = "linked-hash-map" 634 | version = "0.5.6" 635 | source = "registry+https://github.com/rust-lang/crates.io-index" 636 | checksum = "0717cef1bc8b636c6e1c1bbdefc09e6322da8a9321966e8928ef80d20f7f770f" 637 | 638 | [[package]] 639 | name = "lock_api" 640 | version = "0.4.9" 641 | source = "registry+https://github.com/rust-lang/crates.io-index" 642 | checksum = "435011366fe56583b16cf956f9df0095b405b82d76425bc8981c0e22e60ec4df" 643 | dependencies = [ 644 | "autocfg", 645 | "scopeguard", 646 | ] 647 | 648 | [[package]] 649 | name = "log" 650 | version = "0.4.17" 651 | source = "registry+https://github.com/rust-lang/crates.io-index" 652 | checksum = "abb12e687cfb44aa40f41fc3978ef76448f9b6038cad6aef4259d3c095a2382e" 653 | dependencies = [ 654 | "cfg-if", 655 | ] 656 | 657 | [[package]] 658 | name = "memchr" 659 | version = "2.5.0" 660 | source = "registry+https://github.com/rust-lang/crates.io-index" 661 | checksum = "2dffe52ecf27772e601905b7522cb4ef790d2cc203488bbd0e2fe85fcb74566d" 662 | 663 | [[package]] 664 | name = "mime" 665 | version = "0.3.16" 666 | source = "registry+https://github.com/rust-lang/crates.io-index" 667 | checksum = "2a60c7ce501c71e03a9c9c0d35b861413ae925bd979cc7a4e30d060069aaac8d" 668 | 669 | [[package]] 670 | name = "miniz_oxide" 671 | version = "0.5.4" 672 | source = "registry+https://github.com/rust-lang/crates.io-index" 673 | checksum = "96590ba8f175222643a85693f33d26e9c8a015f599c216509b1a6894af675d34" 674 | dependencies = [ 675 | "adler", 676 | ] 677 | 678 | [[package]] 679 | name = "mio" 680 | version = "0.8.5" 681 | source = "registry+https://github.com/rust-lang/crates.io-index" 682 | checksum = "e5d732bc30207a6423068df043e3d02e0735b155ad7ce1a6f76fe2baa5b158de" 683 | dependencies = [ 684 | "libc", 685 | "log", 686 | "wasi 0.11.0+wasi-snapshot-preview1", 687 | "windows-sys 0.42.0", 688 | ] 689 | 690 | [[package]] 691 | name = "native-tls" 692 | version = "0.2.11" 693 | source = "registry+https://github.com/rust-lang/crates.io-index" 694 | checksum = "07226173c32f2926027b63cce4bcd8076c3552846cbe7925f3aaffeac0a3b92e" 695 | dependencies = [ 696 | "lazy_static", 697 | "libc", 698 | "log", 699 | "openssl", 700 | "openssl-probe", 701 | "openssl-sys", 702 | "schannel", 703 | "security-framework", 704 | "security-framework-sys", 705 | "tempfile", 706 | ] 707 | 708 | [[package]] 709 | name = "num_cpus" 710 | version = "1.14.0" 711 | source = "registry+https://github.com/rust-lang/crates.io-index" 712 | checksum = "f6058e64324c71e02bc2b150e4f3bc8286db6c83092132ffa3f6b1eab0f9def5" 713 | dependencies = [ 714 | "hermit-abi", 715 | "libc", 716 | ] 717 | 718 | [[package]] 719 | name = "object" 720 | version = "0.29.0" 721 | source = "registry+https://github.com/rust-lang/crates.io-index" 722 | checksum = "21158b2c33aa6d4561f1c0a6ea283ca92bc54802a93b263e910746d679a7eb53" 723 | dependencies = [ 724 | "memchr", 725 | ] 726 | 727 | [[package]] 728 | name = "once_cell" 729 | version = "1.16.0" 730 | source = "registry+https://github.com/rust-lang/crates.io-index" 731 | checksum = "86f0b0d4bf799edbc74508c1e8bf170ff5f41238e5f8225603ca7caaae2b7860" 732 | 733 | [[package]] 734 | name = "opaque-debug" 735 | version = "0.3.0" 736 | source = "registry+https://github.com/rust-lang/crates.io-index" 737 | checksum = "624a8340c38c1b80fd549087862da4ba43e08858af025b236e509b6649fc13d5" 738 | 739 | [[package]] 740 | name = "openssl" 741 | version = "0.10.42" 742 | source = "registry+https://github.com/rust-lang/crates.io-index" 743 | checksum = "12fc0523e3bd51a692c8850d075d74dc062ccf251c0110668cbd921917118a13" 744 | dependencies = [ 745 | "bitflags", 746 | "cfg-if", 747 | "foreign-types", 748 | "libc", 749 | "once_cell", 750 | "openssl-macros", 751 | "openssl-sys", 752 | ] 753 | 754 | [[package]] 755 | name = "openssl-macros" 756 | version = "0.1.0" 757 | source = "registry+https://github.com/rust-lang/crates.io-index" 758 | checksum = "b501e44f11665960c7e7fcf062c7d96a14ade4aa98116c004b2e37b5be7d736c" 759 | dependencies = [ 760 | "proc-macro2", 761 | "quote", 762 | "syn", 763 | ] 764 | 765 | [[package]] 766 | name = "openssl-probe" 767 | version = "0.1.5" 768 | source = "registry+https://github.com/rust-lang/crates.io-index" 769 | checksum = "ff011a302c396a5197692431fc1948019154afc178baf7d8e37367442a4601cf" 770 | 771 | [[package]] 772 | name = "openssl-src" 773 | version = "111.24.0+1.1.1s" 774 | source = "registry+https://github.com/rust-lang/crates.io-index" 775 | checksum = "3498f259dab01178c6228c6b00dcef0ed2a2d5e20d648c017861227773ea4abd" 776 | dependencies = [ 777 | "cc", 778 | ] 779 | 780 | [[package]] 781 | name = "openssl-sys" 782 | version = "0.9.77" 783 | source = "registry+https://github.com/rust-lang/crates.io-index" 784 | checksum = "b03b84c3b2d099b81f0953422b4d4ad58761589d0229b5506356afca05a3670a" 785 | dependencies = [ 786 | "autocfg", 787 | "cc", 788 | "libc", 789 | "openssl-src", 790 | "pkg-config", 791 | "vcpkg", 792 | ] 793 | 794 | [[package]] 795 | name = "parking_lot" 796 | version = "0.11.2" 797 | source = "registry+https://github.com/rust-lang/crates.io-index" 798 | checksum = "7d17b78036a60663b797adeaee46f5c9dfebb86948d1255007a1d6be0271ff99" 799 | dependencies = [ 800 | "instant", 801 | "lock_api", 802 | "parking_lot_core 0.8.5", 803 | ] 804 | 805 | [[package]] 806 | name = "parking_lot" 807 | version = "0.12.1" 808 | source = "registry+https://github.com/rust-lang/crates.io-index" 809 | checksum = "3742b2c103b9f06bc9fff0a37ff4912935851bee6d36f3c02bcc755bcfec228f" 810 | dependencies = [ 811 | "lock_api", 812 | "parking_lot_core 0.9.4", 813 | ] 814 | 815 | [[package]] 816 | name = "parking_lot_core" 817 | version = "0.8.5" 818 | source = "registry+https://github.com/rust-lang/crates.io-index" 819 | checksum = "d76e8e1493bcac0d2766c42737f34458f1c8c50c0d23bcb24ea953affb273216" 820 | dependencies = [ 821 | "cfg-if", 822 | "instant", 823 | "libc", 824 | "redox_syscall", 825 | "smallvec", 826 | "winapi", 827 | ] 828 | 829 | [[package]] 830 | name = "parking_lot_core" 831 | version = "0.9.4" 832 | source = "registry+https://github.com/rust-lang/crates.io-index" 833 | checksum = "4dc9e0dc2adc1c69d09143aff38d3d30c5c3f0df0dad82e6d25547af174ebec0" 834 | dependencies = [ 835 | "cfg-if", 836 | "libc", 837 | "redox_syscall", 838 | "smallvec", 839 | "windows-sys 0.42.0", 840 | ] 841 | 842 | [[package]] 843 | name = "percent-encoding" 844 | version = "2.2.0" 845 | source = "registry+https://github.com/rust-lang/crates.io-index" 846 | checksum = "478c572c3d73181ff3c2539045f6eb99e5491218eae919370993b890cdbdd98e" 847 | 848 | [[package]] 849 | name = "pin-project-lite" 850 | version = "0.2.9" 851 | source = "registry+https://github.com/rust-lang/crates.io-index" 852 | checksum = "e0a7ae3ac2f1173085d398531c705756c94a4c56843785df85a60c1a0afac116" 853 | 854 | [[package]] 855 | name = "pin-utils" 856 | version = "0.1.0" 857 | source = "registry+https://github.com/rust-lang/crates.io-index" 858 | checksum = "8b870d8c151b6f2fb93e84a13146138f05d02ed11c7e7c54f8826aaaf7c9f184" 859 | 860 | [[package]] 861 | name = "pkg-config" 862 | version = "0.3.26" 863 | source = "registry+https://github.com/rust-lang/crates.io-index" 864 | checksum = "6ac9a59f73473f1b8d852421e59e64809f025994837ef743615c6d0c5b305160" 865 | 866 | [[package]] 867 | name = "ppv-lite86" 868 | version = "0.2.17" 869 | source = "registry+https://github.com/rust-lang/crates.io-index" 870 | checksum = "5b40af805b3121feab8a3c29f04d8ad262fa8e0561883e7653e024ae4479e6de" 871 | 872 | [[package]] 873 | name = "proc-macro2" 874 | version = "1.0.47" 875 | source = "registry+https://github.com/rust-lang/crates.io-index" 876 | checksum = "5ea3d908b0e36316caf9e9e2c4625cdde190a7e6f440d794667ed17a1855e725" 877 | dependencies = [ 878 | "unicode-ident", 879 | ] 880 | 881 | [[package]] 882 | name = "quote" 883 | version = "1.0.21" 884 | source = "registry+https://github.com/rust-lang/crates.io-index" 885 | checksum = "bbe448f377a7d6961e30f5955f9b8d106c3f5e449d493ee1b125c1d43c2b5179" 886 | dependencies = [ 887 | "proc-macro2", 888 | ] 889 | 890 | [[package]] 891 | name = "r2d2" 892 | version = "0.8.10" 893 | source = "registry+https://github.com/rust-lang/crates.io-index" 894 | checksum = "51de85fb3fb6524929c8a2eb85e6b6d363de4e8c48f9e2c2eac4944abc181c93" 895 | dependencies = [ 896 | "log", 897 | "parking_lot 0.12.1", 898 | "scheduled-thread-pool", 899 | ] 900 | 901 | [[package]] 902 | name = "r2d2_sqlite" 903 | version = "0.19.0" 904 | source = "registry+https://github.com/rust-lang/crates.io-index" 905 | checksum = "54ca3c9468a76fc2ad724c486a59682fc362efeac7b18d1c012958bc19f34800" 906 | dependencies = [ 907 | "r2d2", 908 | "rusqlite", 909 | ] 910 | 911 | [[package]] 912 | name = "rand" 913 | version = "0.7.3" 914 | source = "registry+https://github.com/rust-lang/crates.io-index" 915 | checksum = "6a6b1679d49b24bbfe0c803429aa1874472f50d9b363131f0e89fc356b544d03" 916 | dependencies = [ 917 | "getrandom 0.1.16", 918 | "libc", 919 | "rand_chacha", 920 | "rand_core", 921 | "rand_hc", 922 | ] 923 | 924 | [[package]] 925 | name = "rand_chacha" 926 | version = "0.2.2" 927 | source = "registry+https://github.com/rust-lang/crates.io-index" 928 | checksum = "f4c8ed856279c9737206bf725bf36935d8666ead7aa69b52be55af369d193402" 929 | dependencies = [ 930 | "ppv-lite86", 931 | "rand_core", 932 | ] 933 | 934 | [[package]] 935 | name = "rand_core" 936 | version = "0.5.1" 937 | source = "registry+https://github.com/rust-lang/crates.io-index" 938 | checksum = "90bde5296fc891b0cef12a6d03ddccc162ce7b2aff54160af9338f8d40df6d19" 939 | dependencies = [ 940 | "getrandom 0.1.16", 941 | ] 942 | 943 | [[package]] 944 | name = "rand_hc" 945 | version = "0.2.0" 946 | source = "registry+https://github.com/rust-lang/crates.io-index" 947 | checksum = "ca3129af7b92a17112d59ad498c6f81eaf463253766b90396d39ea7a39d6613c" 948 | dependencies = [ 949 | "rand_core", 950 | ] 951 | 952 | [[package]] 953 | name = "redox_syscall" 954 | version = "0.2.16" 955 | source = "registry+https://github.com/rust-lang/crates.io-index" 956 | checksum = "fb5a58c1855b4b6819d59012155603f0b22ad30cad752600aadfcb695265519a" 957 | dependencies = [ 958 | "bitflags", 959 | ] 960 | 961 | [[package]] 962 | name = "remove_dir_all" 963 | version = "0.5.3" 964 | source = "registry+https://github.com/rust-lang/crates.io-index" 965 | checksum = "3acd125665422973a33ac9d3dd2df85edad0f4ae9b00dafb1a05e43a9f5ef8e7" 966 | dependencies = [ 967 | "winapi", 968 | ] 969 | 970 | [[package]] 971 | name = "reqwest" 972 | version = "0.11.13" 973 | source = "registry+https://github.com/rust-lang/crates.io-index" 974 | checksum = "68cc60575865c7831548863cc02356512e3f1dc2f3f82cb837d7fc4cc8f3c97c" 975 | dependencies = [ 976 | "base64", 977 | "bytes", 978 | "encoding_rs", 979 | "futures-core", 980 | "futures-util", 981 | "h2", 982 | "http", 983 | "http-body", 984 | "hyper", 985 | "hyper-tls", 986 | "ipnet", 987 | "js-sys", 988 | "log", 989 | "mime", 990 | "native-tls", 991 | "once_cell", 992 | "percent-encoding", 993 | "pin-project-lite", 994 | "serde", 995 | "serde_json", 996 | "serde_urlencoded", 997 | "tokio", 998 | "tokio-native-tls", 999 | "tokio-socks", 1000 | "tower-service", 1001 | "url", 1002 | "wasm-bindgen", 1003 | "wasm-bindgen-futures", 1004 | "web-sys", 1005 | "winreg", 1006 | ] 1007 | 1008 | [[package]] 1009 | name = "rusqlite" 1010 | version = "0.26.3" 1011 | source = "registry+https://github.com/rust-lang/crates.io-index" 1012 | checksum = "4ba4d3462c8b2e4d7f4fcfcf2b296dc6b65404fbbc7b63daa37fd485c149daf7" 1013 | dependencies = [ 1014 | "bitflags", 1015 | "fallible-iterator", 1016 | "fallible-streaming-iterator", 1017 | "hashlink", 1018 | "libsqlite3-sys", 1019 | "memchr", 1020 | "smallvec", 1021 | "uuid", 1022 | ] 1023 | 1024 | [[package]] 1025 | name = "rustc-demangle" 1026 | version = "0.1.21" 1027 | source = "registry+https://github.com/rust-lang/crates.io-index" 1028 | checksum = "7ef03e0a2b150c7a90d01faf6254c9c48a41e95fb2a8c2ac1c6f0d2b9aefc342" 1029 | 1030 | [[package]] 1031 | name = "ryu" 1032 | version = "1.0.11" 1033 | source = "registry+https://github.com/rust-lang/crates.io-index" 1034 | checksum = "4501abdff3ae82a1c1b477a17252eb69cee9e66eb915c1abaa4f44d873df9f09" 1035 | 1036 | [[package]] 1037 | name = "schannel" 1038 | version = "0.1.20" 1039 | source = "registry+https://github.com/rust-lang/crates.io-index" 1040 | checksum = "88d6731146462ea25d9244b2ed5fd1d716d25c52e4d54aa4fb0f3c4e9854dbe2" 1041 | dependencies = [ 1042 | "lazy_static", 1043 | "windows-sys 0.36.1", 1044 | ] 1045 | 1046 | [[package]] 1047 | name = "scheduled-thread-pool" 1048 | version = "0.2.6" 1049 | source = "registry+https://github.com/rust-lang/crates.io-index" 1050 | checksum = "977a7519bff143a44f842fd07e80ad1329295bd71686457f18e496736f4bf9bf" 1051 | dependencies = [ 1052 | "parking_lot 0.12.1", 1053 | ] 1054 | 1055 | [[package]] 1056 | name = "scopeguard" 1057 | version = "1.1.0" 1058 | source = "registry+https://github.com/rust-lang/crates.io-index" 1059 | checksum = "d29ab0c6d3fc0ee92fe66e2d99f700eab17a8d57d1c1d3b748380fb20baa78cd" 1060 | 1061 | [[package]] 1062 | name = "security-framework" 1063 | version = "2.7.0" 1064 | source = "registry+https://github.com/rust-lang/crates.io-index" 1065 | checksum = "2bc1bb97804af6631813c55739f771071e0f2ed33ee20b68c86ec505d906356c" 1066 | dependencies = [ 1067 | "bitflags", 1068 | "core-foundation", 1069 | "core-foundation-sys", 1070 | "libc", 1071 | "security-framework-sys", 1072 | ] 1073 | 1074 | [[package]] 1075 | name = "security-framework-sys" 1076 | version = "2.6.1" 1077 | source = "registry+https://github.com/rust-lang/crates.io-index" 1078 | checksum = "0160a13a177a45bfb43ce71c01580998474f556ad854dcbca936dd2841a5c556" 1079 | dependencies = [ 1080 | "core-foundation-sys", 1081 | "libc", 1082 | ] 1083 | 1084 | [[package]] 1085 | name = "serde" 1086 | version = "1.0.147" 1087 | source = "registry+https://github.com/rust-lang/crates.io-index" 1088 | checksum = "d193d69bae983fc11a79df82342761dfbf28a99fc8d203dca4c3c1b590948965" 1089 | dependencies = [ 1090 | "serde_derive", 1091 | ] 1092 | 1093 | [[package]] 1094 | name = "serde_derive" 1095 | version = "1.0.147" 1096 | source = "registry+https://github.com/rust-lang/crates.io-index" 1097 | checksum = "4f1d362ca8fc9c3e3a7484440752472d68a6caa98f1ab81d99b5dfe517cec852" 1098 | dependencies = [ 1099 | "proc-macro2", 1100 | "quote", 1101 | "syn", 1102 | ] 1103 | 1104 | [[package]] 1105 | name = "serde_json" 1106 | version = "1.0.89" 1107 | source = "registry+https://github.com/rust-lang/crates.io-index" 1108 | checksum = "020ff22c755c2ed3f8cf162dbb41a7268d934702f3ed3631656ea597e08fc3db" 1109 | dependencies = [ 1110 | "itoa", 1111 | "ryu", 1112 | "serde", 1113 | ] 1114 | 1115 | [[package]] 1116 | name = "serde_urlencoded" 1117 | version = "0.7.1" 1118 | source = "registry+https://github.com/rust-lang/crates.io-index" 1119 | checksum = "d3491c14715ca2294c4d6a88f15e84739788c1d030eed8c110436aafdaa2f3fd" 1120 | dependencies = [ 1121 | "form_urlencoded", 1122 | "itoa", 1123 | "ryu", 1124 | "serde", 1125 | ] 1126 | 1127 | [[package]] 1128 | name = "serde_yaml" 1129 | version = "0.8.26" 1130 | source = "registry+https://github.com/rust-lang/crates.io-index" 1131 | checksum = "578a7433b776b56a35785ed5ce9a7e777ac0598aac5a6dd1b4b18a307c7fc71b" 1132 | dependencies = [ 1133 | "indexmap", 1134 | "ryu", 1135 | "serde", 1136 | "yaml-rust", 1137 | ] 1138 | 1139 | [[package]] 1140 | name = "sha2" 1141 | version = "0.9.9" 1142 | source = "registry+https://github.com/rust-lang/crates.io-index" 1143 | checksum = "4d58a1e1bf39749807d89cf2d98ac2dfa0ff1cb3faa38fbb64dd88ac8013d800" 1144 | dependencies = [ 1145 | "block-buffer", 1146 | "cfg-if", 1147 | "cpufeatures", 1148 | "digest", 1149 | "opaque-debug", 1150 | ] 1151 | 1152 | [[package]] 1153 | name = "sha3" 1154 | version = "0.9.1" 1155 | source = "registry+https://github.com/rust-lang/crates.io-index" 1156 | checksum = "f81199417d4e5de3f04b1e871023acea7389672c4135918f05aa9cbf2f2fa809" 1157 | dependencies = [ 1158 | "block-buffer", 1159 | "digest", 1160 | "keccak", 1161 | "opaque-debug", 1162 | ] 1163 | 1164 | [[package]] 1165 | name = "signal-hook-registry" 1166 | version = "1.4.0" 1167 | source = "registry+https://github.com/rust-lang/crates.io-index" 1168 | checksum = "e51e73328dc4ac0c7ccbda3a494dfa03df1de2f46018127f60c693f2648455b0" 1169 | dependencies = [ 1170 | "libc", 1171 | ] 1172 | 1173 | [[package]] 1174 | name = "signature" 1175 | version = "1.6.4" 1176 | source = "registry+https://github.com/rust-lang/crates.io-index" 1177 | checksum = "74233d3b3b2f6d4b006dc19dee745e73e2a6bfb6f93607cd3b02bd5b00797d7c" 1178 | 1179 | [[package]] 1180 | name = "slab" 1181 | version = "0.4.7" 1182 | source = "registry+https://github.com/rust-lang/crates.io-index" 1183 | checksum = "4614a76b2a8be0058caa9dbbaf66d988527d86d003c11a94fbd335d7661edcef" 1184 | dependencies = [ 1185 | "autocfg", 1186 | ] 1187 | 1188 | [[package]] 1189 | name = "smallvec" 1190 | version = "1.10.0" 1191 | source = "registry+https://github.com/rust-lang/crates.io-index" 1192 | checksum = "a507befe795404456341dfab10cef66ead4c041f62b8b11bbb92bffe5d0953e0" 1193 | 1194 | [[package]] 1195 | name = "socket2" 1196 | version = "0.4.7" 1197 | source = "registry+https://github.com/rust-lang/crates.io-index" 1198 | checksum = "02e2d2db9033d13a1567121ddd7a095ee144db4e1ca1b1bda3419bc0da294ebd" 1199 | dependencies = [ 1200 | "libc", 1201 | "winapi", 1202 | ] 1203 | 1204 | [[package]] 1205 | name = "subtle" 1206 | version = "2.4.1" 1207 | source = "registry+https://github.com/rust-lang/crates.io-index" 1208 | checksum = "6bdef32e8150c2a081110b42772ffe7d7c9032b606bc226c8260fd97e0976601" 1209 | 1210 | [[package]] 1211 | name = "syn" 1212 | version = "1.0.103" 1213 | source = "registry+https://github.com/rust-lang/crates.io-index" 1214 | checksum = "a864042229133ada95abf3b54fdc62ef5ccabe9515b64717bcb9a1919e59445d" 1215 | dependencies = [ 1216 | "proc-macro2", 1217 | "quote", 1218 | "unicode-ident", 1219 | ] 1220 | 1221 | [[package]] 1222 | name = "synstructure" 1223 | version = "0.12.6" 1224 | source = "registry+https://github.com/rust-lang/crates.io-index" 1225 | checksum = "f36bdaa60a83aca3921b5259d5400cbf5e90fc51931376a9bd4a0eb79aa7210f" 1226 | dependencies = [ 1227 | "proc-macro2", 1228 | "quote", 1229 | "syn", 1230 | "unicode-xid", 1231 | ] 1232 | 1233 | [[package]] 1234 | name = "tempfile" 1235 | version = "3.3.0" 1236 | source = "registry+https://github.com/rust-lang/crates.io-index" 1237 | checksum = "5cdb1ef4eaeeaddc8fbd371e5017057064af0911902ef36b39801f67cc6d79e4" 1238 | dependencies = [ 1239 | "cfg-if", 1240 | "fastrand", 1241 | "libc", 1242 | "redox_syscall", 1243 | "remove_dir_all", 1244 | "winapi", 1245 | ] 1246 | 1247 | [[package]] 1248 | name = "thiserror" 1249 | version = "1.0.37" 1250 | source = "registry+https://github.com/rust-lang/crates.io-index" 1251 | checksum = "10deb33631e3c9018b9baf9dcbbc4f737320d2b576bac10f6aefa048fa407e3e" 1252 | dependencies = [ 1253 | "thiserror-impl", 1254 | ] 1255 | 1256 | [[package]] 1257 | name = "thiserror-impl" 1258 | version = "1.0.37" 1259 | source = "registry+https://github.com/rust-lang/crates.io-index" 1260 | checksum = "982d17546b47146b28f7c22e3d08465f6b8903d0ea13c1660d9d84a6e7adcdbb" 1261 | dependencies = [ 1262 | "proc-macro2", 1263 | "quote", 1264 | "syn", 1265 | ] 1266 | 1267 | [[package]] 1268 | name = "tinyvec" 1269 | version = "1.6.0" 1270 | source = "registry+https://github.com/rust-lang/crates.io-index" 1271 | checksum = "87cc5ceb3875bb20c2890005a4e226a4651264a5c75edb2421b52861a0a0cb50" 1272 | dependencies = [ 1273 | "tinyvec_macros", 1274 | ] 1275 | 1276 | [[package]] 1277 | name = "tinyvec_macros" 1278 | version = "0.1.0" 1279 | source = "registry+https://github.com/rust-lang/crates.io-index" 1280 | checksum = "cda74da7e1a664f795bb1f8a87ec406fb89a02522cf6e50620d016add6dbbf5c" 1281 | 1282 | [[package]] 1283 | name = "tokio" 1284 | version = "1.22.0" 1285 | source = "registry+https://github.com/rust-lang/crates.io-index" 1286 | checksum = "d76ce4a75fb488c605c54bf610f221cea8b0dafb53333c1a67e8ee199dcd2ae3" 1287 | dependencies = [ 1288 | "autocfg", 1289 | "bytes", 1290 | "libc", 1291 | "memchr", 1292 | "mio", 1293 | "num_cpus", 1294 | "parking_lot 0.12.1", 1295 | "pin-project-lite", 1296 | "signal-hook-registry", 1297 | "socket2", 1298 | "tokio-macros", 1299 | "winapi", 1300 | ] 1301 | 1302 | [[package]] 1303 | name = "tokio-macros" 1304 | version = "1.8.0" 1305 | source = "registry+https://github.com/rust-lang/crates.io-index" 1306 | checksum = "9724f9a975fb987ef7a3cd9be0350edcbe130698af5b8f7a631e23d42d052484" 1307 | dependencies = [ 1308 | "proc-macro2", 1309 | "quote", 1310 | "syn", 1311 | ] 1312 | 1313 | [[package]] 1314 | name = "tokio-native-tls" 1315 | version = "0.3.0" 1316 | source = "registry+https://github.com/rust-lang/crates.io-index" 1317 | checksum = "f7d995660bd2b7f8c1568414c1126076c13fbb725c40112dc0120b78eb9b717b" 1318 | dependencies = [ 1319 | "native-tls", 1320 | "tokio", 1321 | ] 1322 | 1323 | [[package]] 1324 | name = "tokio-socks" 1325 | version = "0.5.1" 1326 | source = "registry+https://github.com/rust-lang/crates.io-index" 1327 | checksum = "51165dfa029d2a65969413a6cc96f354b86b464498702f174a4efa13608fd8c0" 1328 | dependencies = [ 1329 | "either", 1330 | "futures-util", 1331 | "thiserror", 1332 | "tokio", 1333 | ] 1334 | 1335 | [[package]] 1336 | name = "tokio-util" 1337 | version = "0.7.4" 1338 | source = "registry+https://github.com/rust-lang/crates.io-index" 1339 | checksum = "0bb2e075f03b3d66d8d8785356224ba688d2906a371015e225beeb65ca92c740" 1340 | dependencies = [ 1341 | "bytes", 1342 | "futures-core", 1343 | "futures-sink", 1344 | "pin-project-lite", 1345 | "tokio", 1346 | "tracing", 1347 | ] 1348 | 1349 | [[package]] 1350 | name = "tower-service" 1351 | version = "0.3.2" 1352 | source = "registry+https://github.com/rust-lang/crates.io-index" 1353 | checksum = "b6bc1c9ce2b5135ac7f93c72918fc37feb872bdc6a5533a8b85eb4b86bfdae52" 1354 | 1355 | [[package]] 1356 | name = "tracing" 1357 | version = "0.1.37" 1358 | source = "registry+https://github.com/rust-lang/crates.io-index" 1359 | checksum = "8ce8c33a8d48bd45d624a6e523445fd21ec13d3653cd51f681abf67418f54eb8" 1360 | dependencies = [ 1361 | "cfg-if", 1362 | "pin-project-lite", 1363 | "tracing-core", 1364 | ] 1365 | 1366 | [[package]] 1367 | name = "tracing-core" 1368 | version = "0.1.30" 1369 | source = "registry+https://github.com/rust-lang/crates.io-index" 1370 | checksum = "24eb03ba0eab1fd845050058ce5e616558e8f8d8fca633e6b163fe25c797213a" 1371 | dependencies = [ 1372 | "once_cell", 1373 | ] 1374 | 1375 | [[package]] 1376 | name = "try-lock" 1377 | version = "0.2.3" 1378 | source = "registry+https://github.com/rust-lang/crates.io-index" 1379 | checksum = "59547bce71d9c38b83d9c0e92b6066c4253371f15005def0c30d9657f50c7642" 1380 | 1381 | [[package]] 1382 | name = "typenum" 1383 | version = "1.15.0" 1384 | source = "registry+https://github.com/rust-lang/crates.io-index" 1385 | checksum = "dcf81ac59edc17cc8697ff311e8f5ef2d99fcbd9817b34cec66f90b6c3dfd987" 1386 | 1387 | [[package]] 1388 | name = "unicode-bidi" 1389 | version = "0.3.8" 1390 | source = "registry+https://github.com/rust-lang/crates.io-index" 1391 | checksum = "099b7128301d285f79ddd55b9a83d5e6b9e97c92e0ea0daebee7263e932de992" 1392 | 1393 | [[package]] 1394 | name = "unicode-ident" 1395 | version = "1.0.5" 1396 | source = "registry+https://github.com/rust-lang/crates.io-index" 1397 | checksum = "6ceab39d59e4c9499d4e5a8ee0e2735b891bb7308ac83dfb4e80cad195c9f6f3" 1398 | 1399 | [[package]] 1400 | name = "unicode-normalization" 1401 | version = "0.1.22" 1402 | source = "registry+https://github.com/rust-lang/crates.io-index" 1403 | checksum = "5c5713f0fc4b5db668a2ac63cdb7bb4469d8c9fed047b1d0292cc7b0ce2ba921" 1404 | dependencies = [ 1405 | "tinyvec", 1406 | ] 1407 | 1408 | [[package]] 1409 | name = "unicode-xid" 1410 | version = "0.2.4" 1411 | source = "registry+https://github.com/rust-lang/crates.io-index" 1412 | checksum = "f962df74c8c05a667b5ee8bcf162993134c104e96440b663c8daa176dc772d8c" 1413 | 1414 | [[package]] 1415 | name = "url" 1416 | version = "2.3.1" 1417 | source = "registry+https://github.com/rust-lang/crates.io-index" 1418 | checksum = "0d68c799ae75762b8c3fe375feb6600ef5602c883c5d21eb51c09f22b83c4643" 1419 | dependencies = [ 1420 | "form_urlencoded", 1421 | "idna", 1422 | "percent-encoding", 1423 | ] 1424 | 1425 | [[package]] 1426 | name = "uuid" 1427 | version = "0.8.2" 1428 | source = "registry+https://github.com/rust-lang/crates.io-index" 1429 | checksum = "bc5cf98d8186244414c848017f0e2676b3fcb46807f6668a97dfe67359a3c4b7" 1430 | 1431 | [[package]] 1432 | name = "vcpkg" 1433 | version = "0.2.15" 1434 | source = "registry+https://github.com/rust-lang/crates.io-index" 1435 | checksum = "accd4ea62f7bb7a82fe23066fb0957d48ef677f6eeb8215f372f52e48bb32426" 1436 | 1437 | [[package]] 1438 | name = "version_check" 1439 | version = "0.9.4" 1440 | source = "registry+https://github.com/rust-lang/crates.io-index" 1441 | checksum = "49874b5167b65d7193b8aba1567f5c7d93d001cafc34600cee003eda787e483f" 1442 | 1443 | [[package]] 1444 | name = "want" 1445 | version = "0.3.0" 1446 | source = "registry+https://github.com/rust-lang/crates.io-index" 1447 | checksum = "1ce8a968cb1cd110d136ff8b819a556d6fb6d919363c61534f6860c7eb172ba0" 1448 | dependencies = [ 1449 | "log", 1450 | "try-lock", 1451 | ] 1452 | 1453 | [[package]] 1454 | name = "wasi" 1455 | version = "0.9.0+wasi-snapshot-preview1" 1456 | source = "registry+https://github.com/rust-lang/crates.io-index" 1457 | checksum = "cccddf32554fecc6acb585f82a32a72e28b48f8c4c1883ddfeeeaa96f7d8e519" 1458 | 1459 | [[package]] 1460 | name = "wasi" 1461 | version = "0.11.0+wasi-snapshot-preview1" 1462 | source = "registry+https://github.com/rust-lang/crates.io-index" 1463 | checksum = "9c8d87e72b64a3b4db28d11ce29237c246188f4f51057d65a7eab63b7987e423" 1464 | 1465 | [[package]] 1466 | name = "wasm-bindgen" 1467 | version = "0.2.83" 1468 | source = "registry+https://github.com/rust-lang/crates.io-index" 1469 | checksum = "eaf9f5aceeec8be17c128b2e93e031fb8a4d469bb9c4ae2d7dc1888b26887268" 1470 | dependencies = [ 1471 | "cfg-if", 1472 | "wasm-bindgen-macro", 1473 | ] 1474 | 1475 | [[package]] 1476 | name = "wasm-bindgen-backend" 1477 | version = "0.2.83" 1478 | source = "registry+https://github.com/rust-lang/crates.io-index" 1479 | checksum = "4c8ffb332579b0557b52d268b91feab8df3615f265d5270fec2a8c95b17c1142" 1480 | dependencies = [ 1481 | "bumpalo", 1482 | "log", 1483 | "once_cell", 1484 | "proc-macro2", 1485 | "quote", 1486 | "syn", 1487 | "wasm-bindgen-shared", 1488 | ] 1489 | 1490 | [[package]] 1491 | name = "wasm-bindgen-futures" 1492 | version = "0.4.33" 1493 | source = "registry+https://github.com/rust-lang/crates.io-index" 1494 | checksum = "23639446165ca5a5de86ae1d8896b737ae80319560fbaa4c2887b7da6e7ebd7d" 1495 | dependencies = [ 1496 | "cfg-if", 1497 | "js-sys", 1498 | "wasm-bindgen", 1499 | "web-sys", 1500 | ] 1501 | 1502 | [[package]] 1503 | name = "wasm-bindgen-macro" 1504 | version = "0.2.83" 1505 | source = "registry+https://github.com/rust-lang/crates.io-index" 1506 | checksum = "052be0f94026e6cbc75cdefc9bae13fd6052cdcaf532fa6c45e7ae33a1e6c810" 1507 | dependencies = [ 1508 | "quote", 1509 | "wasm-bindgen-macro-support", 1510 | ] 1511 | 1512 | [[package]] 1513 | name = "wasm-bindgen-macro-support" 1514 | version = "0.2.83" 1515 | source = "registry+https://github.com/rust-lang/crates.io-index" 1516 | checksum = "07bc0c051dc5f23e307b13285f9d75df86bfdf816c5721e573dec1f9b8aa193c" 1517 | dependencies = [ 1518 | "proc-macro2", 1519 | "quote", 1520 | "syn", 1521 | "wasm-bindgen-backend", 1522 | "wasm-bindgen-shared", 1523 | ] 1524 | 1525 | [[package]] 1526 | name = "wasm-bindgen-shared" 1527 | version = "0.2.83" 1528 | source = "registry+https://github.com/rust-lang/crates.io-index" 1529 | checksum = "1c38c045535d93ec4f0b4defec448e4291638ee608530863b1e2ba115d4fff7f" 1530 | 1531 | [[package]] 1532 | name = "web-sys" 1533 | version = "0.3.60" 1534 | source = "registry+https://github.com/rust-lang/crates.io-index" 1535 | checksum = "bcda906d8be16e728fd5adc5b729afad4e444e106ab28cd1c7256e54fa61510f" 1536 | dependencies = [ 1537 | "js-sys", 1538 | "wasm-bindgen", 1539 | ] 1540 | 1541 | [[package]] 1542 | name = "winapi" 1543 | version = "0.3.9" 1544 | source = "registry+https://github.com/rust-lang/crates.io-index" 1545 | checksum = "5c839a674fcd7a98952e593242ea400abe93992746761e38641405d28b00f419" 1546 | dependencies = [ 1547 | "winapi-i686-pc-windows-gnu", 1548 | "winapi-x86_64-pc-windows-gnu", 1549 | ] 1550 | 1551 | [[package]] 1552 | name = "winapi-i686-pc-windows-gnu" 1553 | version = "0.4.0" 1554 | source = "registry+https://github.com/rust-lang/crates.io-index" 1555 | checksum = "ac3b87c63620426dd9b991e5ce0329eff545bccbbb34f3be09ff6fb6ab51b7b6" 1556 | 1557 | [[package]] 1558 | name = "winapi-x86_64-pc-windows-gnu" 1559 | version = "0.4.0" 1560 | source = "registry+https://github.com/rust-lang/crates.io-index" 1561 | checksum = "712e227841d057c1ee1cd2fb22fa7e5a5461ae8e48fa2ca79ec42cfc1931183f" 1562 | 1563 | [[package]] 1564 | name = "windows-sys" 1565 | version = "0.36.1" 1566 | source = "registry+https://github.com/rust-lang/crates.io-index" 1567 | checksum = "ea04155a16a59f9eab786fe12a4a450e75cdb175f9e0d80da1e17db09f55b8d2" 1568 | dependencies = [ 1569 | "windows_aarch64_msvc 0.36.1", 1570 | "windows_i686_gnu 0.36.1", 1571 | "windows_i686_msvc 0.36.1", 1572 | "windows_x86_64_gnu 0.36.1", 1573 | "windows_x86_64_msvc 0.36.1", 1574 | ] 1575 | 1576 | [[package]] 1577 | name = "windows-sys" 1578 | version = "0.42.0" 1579 | source = "registry+https://github.com/rust-lang/crates.io-index" 1580 | checksum = "5a3e1820f08b8513f676f7ab6c1f99ff312fb97b553d30ff4dd86f9f15728aa7" 1581 | dependencies = [ 1582 | "windows_aarch64_gnullvm", 1583 | "windows_aarch64_msvc 0.42.0", 1584 | "windows_i686_gnu 0.42.0", 1585 | "windows_i686_msvc 0.42.0", 1586 | "windows_x86_64_gnu 0.42.0", 1587 | "windows_x86_64_gnullvm", 1588 | "windows_x86_64_msvc 0.42.0", 1589 | ] 1590 | 1591 | [[package]] 1592 | name = "windows_aarch64_gnullvm" 1593 | version = "0.42.0" 1594 | source = "registry+https://github.com/rust-lang/crates.io-index" 1595 | checksum = "41d2aa71f6f0cbe00ae5167d90ef3cfe66527d6f613ca78ac8024c3ccab9a19e" 1596 | 1597 | [[package]] 1598 | name = "windows_aarch64_msvc" 1599 | version = "0.36.1" 1600 | source = "registry+https://github.com/rust-lang/crates.io-index" 1601 | checksum = "9bb8c3fd39ade2d67e9874ac4f3db21f0d710bee00fe7cab16949ec184eeaa47" 1602 | 1603 | [[package]] 1604 | name = "windows_aarch64_msvc" 1605 | version = "0.42.0" 1606 | source = "registry+https://github.com/rust-lang/crates.io-index" 1607 | checksum = "dd0f252f5a35cac83d6311b2e795981f5ee6e67eb1f9a7f64eb4500fbc4dcdb4" 1608 | 1609 | [[package]] 1610 | name = "windows_i686_gnu" 1611 | version = "0.36.1" 1612 | source = "registry+https://github.com/rust-lang/crates.io-index" 1613 | checksum = "180e6ccf01daf4c426b846dfc66db1fc518f074baa793aa7d9b9aaeffad6a3b6" 1614 | 1615 | [[package]] 1616 | name = "windows_i686_gnu" 1617 | version = "0.42.0" 1618 | source = "registry+https://github.com/rust-lang/crates.io-index" 1619 | checksum = "fbeae19f6716841636c28d695375df17562ca208b2b7d0dc47635a50ae6c5de7" 1620 | 1621 | [[package]] 1622 | name = "windows_i686_msvc" 1623 | version = "0.36.1" 1624 | source = "registry+https://github.com/rust-lang/crates.io-index" 1625 | checksum = "e2e7917148b2812d1eeafaeb22a97e4813dfa60a3f8f78ebe204bcc88f12f024" 1626 | 1627 | [[package]] 1628 | name = "windows_i686_msvc" 1629 | version = "0.42.0" 1630 | source = "registry+https://github.com/rust-lang/crates.io-index" 1631 | checksum = "84c12f65daa39dd2babe6e442988fc329d6243fdce47d7d2d155b8d874862246" 1632 | 1633 | [[package]] 1634 | name = "windows_x86_64_gnu" 1635 | version = "0.36.1" 1636 | source = "registry+https://github.com/rust-lang/crates.io-index" 1637 | checksum = "4dcd171b8776c41b97521e5da127a2d86ad280114807d0b2ab1e462bc764d9e1" 1638 | 1639 | [[package]] 1640 | name = "windows_x86_64_gnu" 1641 | version = "0.42.0" 1642 | source = "registry+https://github.com/rust-lang/crates.io-index" 1643 | checksum = "bf7b1b21b5362cbc318f686150e5bcea75ecedc74dd157d874d754a2ca44b0ed" 1644 | 1645 | [[package]] 1646 | name = "windows_x86_64_gnullvm" 1647 | version = "0.42.0" 1648 | source = "registry+https://github.com/rust-lang/crates.io-index" 1649 | checksum = "09d525d2ba30eeb3297665bd434a54297e4170c7f1a44cad4ef58095b4cd2028" 1650 | 1651 | [[package]] 1652 | name = "windows_x86_64_msvc" 1653 | version = "0.36.1" 1654 | source = "registry+https://github.com/rust-lang/crates.io-index" 1655 | checksum = "c811ca4a8c853ef420abd8592ba53ddbbac90410fab6903b3e79972a631f7680" 1656 | 1657 | [[package]] 1658 | name = "windows_x86_64_msvc" 1659 | version = "0.42.0" 1660 | source = "registry+https://github.com/rust-lang/crates.io-index" 1661 | checksum = "f40009d85759725a34da6d89a94e63d7bdc50a862acf0dbc7c8e488f1edcb6f5" 1662 | 1663 | [[package]] 1664 | name = "winreg" 1665 | version = "0.10.1" 1666 | source = "registry+https://github.com/rust-lang/crates.io-index" 1667 | checksum = "80d0f4e272c85def139476380b12f9ac60926689dd2e01d4923222f40580869d" 1668 | dependencies = [ 1669 | "winapi", 1670 | ] 1671 | 1672 | [[package]] 1673 | name = "yaml-rust" 1674 | version = "0.4.5" 1675 | source = "registry+https://github.com/rust-lang/crates.io-index" 1676 | checksum = "56c1936c4cc7a1c9ab21a1ebb602eb942ba868cbd44a99cb7cdc5892335e1c85" 1677 | dependencies = [ 1678 | "linked-hash-map", 1679 | ] 1680 | 1681 | [[package]] 1682 | name = "zeroize" 1683 | version = "1.3.0" 1684 | source = "registry+https://github.com/rust-lang/crates.io-index" 1685 | checksum = "4756f7db3f7b5574938c3eb1c117038b8e07f95ee6718c0efad4ac21508f1efd" 1686 | dependencies = [ 1687 | "zeroize_derive", 1688 | ] 1689 | 1690 | [[package]] 1691 | name = "zeroize_derive" 1692 | version = "1.3.2" 1693 | source = "registry+https://github.com/rust-lang/crates.io-index" 1694 | checksum = "3f8f187641dad4f680d25c4bfc4225b418165984179f26ca76ec4fb6441d3a17" 1695 | dependencies = [ 1696 | "proc-macro2", 1697 | "quote", 1698 | "syn", 1699 | "synstructure", 1700 | ] 1701 | --------------------------------------------------------------------------------