diff --git a/src-tauri/Cargo.lock b/src-tauri/Cargo.lock
index 4fb17ed..a5dfbee 100644
--- a/src-tauri/Cargo.lock
+++ b/src-tauri/Cargo.lock
@@ -88,7 +88,13 @@ checksum = "a23eb6b1614318a8071c9b2521f36b424b2c83db5eb3a0fead4a6c0809af6e61"
name = "app"
version = "0.1.0"
dependencies = [
+ "anyhow",
+ "chrono",
+ "diqwest",
+ "icalendar",
"log",
+ "minidom",
+ "reqwest",
"serde",
"serde_json",
"tauri",
@@ -393,6 +399,15 @@ dependencies = [
"toml 0.9.7",
]
+[[package]]
+name = "castaway"
+version = "0.2.4"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "dec551ab6e7578819132c713a93c022a05d60159dc86e7a7050223577484c55a"
+dependencies = [
+ "rustversion",
+]
+
[[package]]
name = "cc"
version = "1.2.39"
@@ -449,11 +464,34 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "145052bdd345b87320e369255277e3fb5152762ad123a901ef5c262dd38fe8d2"
dependencies = [
"iana-time-zone",
+ "js-sys",
"num-traits",
"serde",
+ "wasm-bindgen",
"windows-link 0.2.0",
]
+[[package]]
+name = "chrono-tz"
+version = "0.10.3"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "efdce149c370f133a071ca8ef6ea340b7b88748ab0810097a9e2976eaa34b4f3"
+dependencies = [
+ "chrono",
+ "chrono-tz-build",
+ "phf 0.11.3",
+]
+
+[[package]]
+name = "chrono-tz-build"
+version = "0.4.1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "8f10f8c9340e31fc120ff885fcdb54a0b48e474bbd77cab557f0c30a3e569402"
+dependencies = [
+ "parse-zoneinfo",
+ "phf_codegen 0.11.3",
+]
+
[[package]]
name = "combine"
version = "4.6.7"
@@ -464,6 +502,19 @@ dependencies = [
"memchr",
]
+[[package]]
+name = "compact_str"
+version = "0.7.1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "f86b9c4c00838774a6d902ef931eff7470720c51d90c2e32cfe15dc304737b3f"
+dependencies = [
+ "castaway",
+ "cfg-if",
+ "itoa",
+ "ryu",
+ "static_assertions",
+]
+
[[package]]
name = "convert_case"
version = "0.4.0"
@@ -678,6 +729,30 @@ dependencies = [
"crypto-common",
]
+[[package]]
+name = "digest_auth"
+version = "0.3.1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "3054f4e81d395e50822796c5e99ca522e6ba7be98947d6d4b0e5e61640bdb894"
+dependencies = [
+ "digest",
+ "hex",
+ "md-5",
+ "rand 0.8.5",
+ "sha2",
+]
+
+[[package]]
+name = "diqwest"
+version = "3.1.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "753559f3659efa905c873c59efad5ef0f5e94912b3dbd2069331c554daa33d81"
+dependencies = [
+ "digest_auth",
+ "reqwest",
+ "url",
+]
+
[[package]]
name = "dirs"
version = "6.0.0"
@@ -1512,6 +1587,20 @@ dependencies = [
"cc",
]
+[[package]]
+name = "icalendar"
+version = "0.17.5"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "f25bc68d1c3113be52919708c870cabe55ba0646b9dade87913fe565aa956a3b"
+dependencies = [
+ "chrono",
+ "chrono-tz",
+ "iso8601",
+ "nom",
+ "nom-language",
+ "uuid",
+]
+
[[package]]
name = "ico"
version = "0.4.0"
@@ -1694,6 +1783,15 @@ dependencies = [
"serde",
]
+[[package]]
+name = "iso8601"
+version = "0.6.3"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "e1082f0c48f143442a1ac6122f67e360ceee130b967af4d50996e5154a45df46"
+dependencies = [
+ "nom",
+]
+
[[package]]
name = "itoa"
version = "1.0.15"
@@ -1924,6 +2022,16 @@ version = "0.1.10"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "2532096657941c2fea9c289d370a250971c689d4f143798ff67113ec042024a5"
+[[package]]
+name = "md-5"
+version = "0.10.6"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "d89e7ee0cfbedfc4da3340218492196241d89eefb6dab27de5df917a6d2e78cf"
+dependencies = [
+ "cfg-if",
+ "digest",
+]
+
[[package]]
name = "memchr"
version = "2.7.6"
@@ -1945,6 +2053,15 @@ version = "0.3.17"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "6877bb514081ee2a7ff5ef9de3281f14a4dd4bceac4c09388074a6b5df8a139a"
+[[package]]
+name = "minidom"
+version = "0.17.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "b1d0766d3b25519bd1462d4ca35480e1efabe19727bc4c269aba3b255c0a7a66"
+dependencies = [
+ "rxml",
+]
+
[[package]]
name = "miniz_oxide"
version = "0.8.9"
@@ -2029,6 +2146,24 @@ version = "0.1.14"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "72ef4a56884ca558e5ddb05a1d1e7e1bfd9a68d9ed024c21704cc98872dae1bb"
+[[package]]
+name = "nom"
+version = "8.0.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "df9761775871bdef83bee530e60050f7e54b1105350d6884eb0fb4f46c2f9405"
+dependencies = [
+ "memchr",
+]
+
+[[package]]
+name = "nom-language"
+version = "0.1.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "2de2bc5b451bfedaef92c90b8939a8fff5770bdcc1fafd6239d086aab8fa6b29"
+dependencies = [
+ "nom",
+]
+
[[package]]
name = "num-conv"
version = "0.1.0"
@@ -2381,6 +2516,15 @@ dependencies = [
"windows-targets 0.52.6",
]
+[[package]]
+name = "parse-zoneinfo"
+version = "0.3.1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "1f2a05b18d44e2957b88f96ba460715e295bc1d7510468a2f3d3b44535d26c24"
+dependencies = [
+ "regex",
+]
+
[[package]]
name = "percent-encoding"
version = "2.3.2"
@@ -3135,6 +3279,26 @@ version = "1.0.22"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "b39cdef0fa800fc44525c84ccb54a029961a8215f9619753635a9c0d2538d46d"
+[[package]]
+name = "rxml"
+version = "0.13.3"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "f288457ad3607c08953ca5604229ebb03878a0b4491d8f545d547281c2b3e0c5"
+dependencies = [
+ "bytes",
+ "futures-core",
+ "rxml_validation",
+]
+
+[[package]]
+name = "rxml_validation"
+version = "0.11.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "826e80413b9a35e9d33217b3dcac04cf95f6559d15944b93887a08be5496c4a4"
+dependencies = [
+ "compact_str",
+]
+
[[package]]
name = "ryu"
version = "1.0.20"
@@ -3529,6 +3693,12 @@ version = "1.2.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "a8f112729512f8e442d81f95a8a7ddf2b7c6b8a1a6f509a95864142b30cab2d3"
+[[package]]
+name = "static_assertions"
+version = "1.1.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "a2eb9349b6444b326872e140eb1cf5e7c522154d69e7a0ffb0fb81c06b37543f"
+
[[package]]
name = "string_cache"
version = "0.8.9"
diff --git a/src-tauri/Cargo.toml b/src-tauri/Cargo.toml
index 4ca5cca..cdee57d 100644
--- a/src-tauri/Cargo.toml
+++ b/src-tauri/Cargo.toml
@@ -27,3 +27,9 @@ tauri-plugin-keep-screen-on = "0.1.2"
tauri-plugin-upload = "2"
tauri-plugin-fs = "2"
tauri-plugin-tts = { git = "https://github.com/cfpwastaken/tauri-plugin-tts.git" }
+reqwest = { version = "0.12.23", default-features = false, features = ["rustls-tls"] }
+diqwest = "3.1.0"
+minidom = "0.17.0"
+icalendar = { version = "0.17.5", features = ["chrono-tz"] }
+anyhow = "1.0.100"
+chrono = "0.4.42"
diff --git a/src-tauri/src/dav.rs b/src-tauri/src/dav.rs
new file mode 100644
index 0000000..6701421
--- /dev/null
+++ b/src-tauri/src/dav.rs
@@ -0,0 +1,389 @@
+use std::fmt::Display;
+
+use diqwest::WithDigestAuth;
+use icalendar::{Calendar};
+use minidom::Element;
+use reqwest::{
+ header::{CONTENT_TYPE, USER_AGENT}, Client, Method, RequestBuilder, Url
+};
+use serde::{Deserialize, Serialize};
+
+static PRINCIPAL_BODY: &str = r#"
+
+
+
+
+
+"#;
+
+static HOMESET_BODY: &str = r#"
+
+
+
+
+
+"#;
+
+static CAL_BODY: &str = r#"
+
+
+
+
+
+
+
+"#;
+
+static EVENT_BODY: &str = r#"
+
+
+
+
+
+
+
+
+
+
+
+
+
+"#;
+
+pub fn find_elems(root: &Element, tag: String) -> Vec<&Element> {
+ let mut elems: Vec<&Element> = Vec::new();
+
+ for el in root.children() {
+ if el.name() == tag {
+ elems.push(el);
+ } else {
+ let ret = find_elems(el, tag.clone());
+ elems.extend(ret);
+ }
+ }
+ elems
+}
+
+pub fn find_elem(root: &Element, tag: String) -> Option<&Element> {
+ if root.name() == tag {
+ return Some(root);
+ }
+
+ for el in root.children() {
+ if el.name() == tag {
+ return Some(el);
+ } else {
+ let ret = find_elem(el, tag.clone());
+ if ret.is_some() {
+ return ret;
+ }
+ }
+ }
+ None
+}
+
+#[derive(Clone, Serialize, Deserialize)]
+pub enum AuthScheme {
+ Basic,
+ Digest,
+}
+
+impl std::str::FromStr for AuthScheme {
+ type Err = String;
+
+ fn from_str(s: &str) -> Result {
+ match s.to_lowercase().as_str() {
+ "basic" => Ok(AuthScheme::Basic),
+ "digest" => Ok(AuthScheme::Digest),
+ _ => Err(format!("Invalid auth scheme: {}", s)),
+ }
+ }
+}
+
+impl Display for AuthScheme {
+ fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
+ match self {
+ AuthScheme::Basic => write!(f, "Basic"),
+ AuthScheme::Digest => write!(f, "Digest"),
+ }
+ }
+}
+
+pub trait ReqwestAuth {
+ fn send_authed(self, scheme: &AuthScheme, username: &str, password: &str) -> impl std::future::Future