mirror of
https://github.com/lennart-k/rustical.git
synced 2026-01-30 10:38:16 +00:00
Compare commits
2 Commits
291bd967da
...
d9da123ff4
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
d9da123ff4 | ||
|
|
eba2f0da9f |
2
.gitignore
vendored
2
.gitignore
vendored
@@ -16,3 +16,5 @@ site
|
|||||||
# Frontend
|
# Frontend
|
||||||
**/node_modules
|
**/node_modules
|
||||||
**/.vite
|
**/.vite
|
||||||
|
|
||||||
|
**/*.snap.new
|
||||||
|
|||||||
43
Cargo.lock
generated
43
Cargo.lock
generated
@@ -477,9 +477,9 @@ checksum = "72b3254f16251a8381aa12e40e3c4d2f0199f8c6508fbecb9d91f575e0fbb8c6"
|
|||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "base64ct"
|
name = "base64ct"
|
||||||
version = "1.8.2"
|
version = "1.8.3"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "7d809780667f4410e7c41b07f52439b94d2bdf8528eeedc287fa38d3b7f95d82"
|
checksum = "2af50177e190e07a26ab74f8b1efbfe2ef87da2116221318cb1c2e82baf7de06"
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "basic-toml"
|
name = "basic-toml"
|
||||||
@@ -1422,9 +1422,9 @@ dependencies = [
|
|||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "getrandom"
|
name = "getrandom"
|
||||||
version = "0.2.16"
|
version = "0.2.17"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "335ff9f135e4384c8150d6f27c6daed433577f86b4750418338c01a1a2528592"
|
checksum = "ff2abc00be7fca6ebc474524697ae276ad847ad0a6b3faa4bcb027e9a4614ad0"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"cfg-if",
|
"cfg-if",
|
||||||
"js-sys",
|
"js-sys",
|
||||||
@@ -1771,7 +1771,7 @@ dependencies = [
|
|||||||
[[package]]
|
[[package]]
|
||||||
name = "ical"
|
name = "ical"
|
||||||
version = "0.11.0"
|
version = "0.11.0"
|
||||||
source = "git+https://github.com/lennart-k/ical-rs?branch=dev#64c342e7258ba445dc91b47cd8e20e0ac8ffc417"
|
source = "git+https://github.com/lennart-k/ical-rs?branch=dev#28e982f928a73f5af13f1e59e28da419567bf93f"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"chrono",
|
"chrono",
|
||||||
"chrono-tz",
|
"chrono-tz",
|
||||||
@@ -2242,7 +2242,7 @@ checksum = "51e219e79014df21a225b1860a479e2dcd7cbd9130f4defd4bd0e191ea31d67d"
|
|||||||
dependencies = [
|
dependencies = [
|
||||||
"base64 0.22.1",
|
"base64 0.22.1",
|
||||||
"chrono",
|
"chrono",
|
||||||
"getrandom 0.2.16",
|
"getrandom 0.2.17",
|
||||||
"http",
|
"http",
|
||||||
"rand 0.8.5",
|
"rand 0.8.5",
|
||||||
"reqwest",
|
"reqwest",
|
||||||
@@ -2521,7 +2521,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
|
|||||||
checksum = "1a2a4764cc1f8d961d802af27193c6f4f0124bd0e76e8393cf818e18880f0524"
|
checksum = "1a2a4764cc1f8d961d802af27193c6f4f0124bd0e76e8393cf818e18880f0524"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"argon2",
|
"argon2",
|
||||||
"getrandom 0.2.16",
|
"getrandom 0.2.17",
|
||||||
"password-hash",
|
"password-hash",
|
||||||
"pbkdf2",
|
"pbkdf2",
|
||||||
"rand_core 0.6.4",
|
"rand_core 0.6.4",
|
||||||
@@ -2847,9 +2847,9 @@ dependencies = [
|
|||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "prost"
|
name = "prost"
|
||||||
version = "0.14.1"
|
version = "0.14.3"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "7231bd9b3d3d33c86b58adbac74b5ec0ad9f496b19d22801d773636feaa95f3d"
|
checksum = "d2ea70524a2f82d518bce41317d0fae74151505651af45faf1ffbd6fd33f0568"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"bytes",
|
"bytes",
|
||||||
"prost-derive",
|
"prost-derive",
|
||||||
@@ -2857,9 +2857,9 @@ dependencies = [
|
|||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "prost-derive"
|
name = "prost-derive"
|
||||||
version = "0.14.1"
|
version = "0.14.3"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "9120690fafc389a67ba3803df527d0ec9cbbc9cc45e4cc20b332996dfb672425"
|
checksum = "27c6023962132f4b30eb4c172c91ce92d933da334c59c23cddee82358ddafb0b"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"anyhow",
|
"anyhow",
|
||||||
"itertools 0.14.0",
|
"itertools 0.14.0",
|
||||||
@@ -2994,7 +2994,7 @@ version = "0.6.4"
|
|||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "ec0be4795e2f6a28069bec0b5ff3e2ac9bafc99e6a9a7dc3547996c5c816922c"
|
checksum = "ec0be4795e2f6a28069bec0b5ff3e2ac9bafc99e6a9a7dc3547996c5c816922c"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"getrandom 0.2.16",
|
"getrandom 0.2.17",
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
@@ -3160,7 +3160,7 @@ checksum = "a4689e6c2294d81e88dc6261c768b63bc4fcdb852be6d1352498b114f61383b7"
|
|||||||
dependencies = [
|
dependencies = [
|
||||||
"cc",
|
"cc",
|
||||||
"cfg-if",
|
"cfg-if",
|
||||||
"getrandom 0.2.16",
|
"getrandom 0.2.17",
|
||||||
"libc",
|
"libc",
|
||||||
"untrusted",
|
"untrusted",
|
||||||
"windows-sys 0.52.0",
|
"windows-sys 0.52.0",
|
||||||
@@ -3350,7 +3350,7 @@ dependencies = [
|
|||||||
"serde",
|
"serde",
|
||||||
"sqlx",
|
"sqlx",
|
||||||
"tokio",
|
"tokio",
|
||||||
"toml 0.9.10+spec-1.1.0",
|
"toml 0.9.11+spec-1.1.0",
|
||||||
"tower",
|
"tower",
|
||||||
"tower-http",
|
"tower-http",
|
||||||
"tower-sessions",
|
"tower-sessions",
|
||||||
@@ -4494,9 +4494,9 @@ dependencies = [
|
|||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "toml"
|
name = "toml"
|
||||||
version = "0.9.10+spec-1.1.0"
|
version = "0.9.11+spec-1.1.0"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "0825052159284a1a8b4d6c0c86cbc801f2da5afd2b225fa548c72f2e74002f48"
|
checksum = "f3afc9a848309fe1aaffaed6e1546a7a14de1f935dc9d89d32afd9a44bab7c46"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"indexmap 2.13.0",
|
"indexmap 2.13.0",
|
||||||
"serde_core",
|
"serde_core",
|
||||||
@@ -4781,16 +4781,13 @@ dependencies = [
|
|||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "tracing-opentelemetry"
|
name = "tracing-opentelemetry"
|
||||||
version = "0.32.0"
|
version = "0.32.1"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "1e6e5658463dd88089aba75c7791e1d3120633b1bfde22478b28f625a9bb1b8e"
|
checksum = "1ac28f2d093c6c477eaa76b23525478f38de514fa9aeb1285738d4b97a9552fc"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"js-sys",
|
"js-sys",
|
||||||
"opentelemetry",
|
"opentelemetry",
|
||||||
"opentelemetry_sdk",
|
|
||||||
"rustversion",
|
|
||||||
"smallvec",
|
"smallvec",
|
||||||
"thiserror 2.0.17",
|
|
||||||
"tracing",
|
"tracing",
|
||||||
"tracing-core",
|
"tracing-core",
|
||||||
"tracing-log",
|
"tracing-log",
|
||||||
@@ -5562,6 +5559,6 @@ dependencies = [
|
|||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "zmij"
|
name = "zmij"
|
||||||
version = "1.0.12"
|
version = "1.0.13"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "2fc5a66a20078bf1251bde995aa2fdcc4b800c70b5d92dd2c62abc5c60f679f8"
|
checksum = "ac93432f5b761b22864c774aac244fa5c0fd877678a4c37ebf6cf42208f9c9ec"
|
||||||
|
|||||||
@@ -11,7 +11,7 @@ use rustical_ical::CalendarObjectType;
|
|||||||
use rustical_store::{
|
use rustical_store::{
|
||||||
Calendar, CalendarMetadata, CalendarStore, SubscriptionStore, auth::Principal,
|
Calendar, CalendarMetadata, CalendarStore, SubscriptionStore, auth::Principal,
|
||||||
};
|
};
|
||||||
use std::{collections::HashMap, io::BufReader};
|
use std::io::BufReader;
|
||||||
use tracing::instrument;
|
use tracing::instrument;
|
||||||
|
|
||||||
#[instrument(skip(resource_service))]
|
#[instrument(skip(resource_service))]
|
||||||
@@ -50,7 +50,7 @@ pub async fn route_import<C: CalendarStore, S: SubscriptionStore>(
|
|||||||
cal.remove_property("X-WR-CALDESC");
|
cal.remove_property("X-WR-CALDESC");
|
||||||
cal.remove_property("X-WR-CALCOLOR");
|
cal.remove_property("X-WR-CALCOLOR");
|
||||||
cal.remove_property("X-WR-TIMEZONE");
|
cal.remove_property("X-WR-TIMEZONE");
|
||||||
let cal = cal.build(&HashMap::new()).unwrap();
|
let cal = cal.build(None).unwrap();
|
||||||
|
|
||||||
// Make sure timezone is valid
|
// Make sure timezone is valid
|
||||||
if let Some(timezone_id) = timezone_id.as_ref() {
|
if let Some(timezone_id) = timezone_id.as_ref() {
|
||||||
|
|||||||
@@ -3,7 +3,6 @@ use ical::{parser::Component, property::ContentLine, types::CalDateTime};
|
|||||||
use rustical_dav::xml::TextMatchElement;
|
use rustical_dav::xml::TextMatchElement;
|
||||||
use rustical_ical::UtcDateTime;
|
use rustical_ical::UtcDateTime;
|
||||||
use rustical_xml::XmlDeserialize;
|
use rustical_xml::XmlDeserialize;
|
||||||
use std::collections::HashMap;
|
|
||||||
|
|
||||||
#[derive(XmlDeserialize, Clone, Debug, PartialEq, Eq)]
|
#[derive(XmlDeserialize, Clone, Debug, PartialEq, Eq)]
|
||||||
#[allow(dead_code)]
|
#[allow(dead_code)]
|
||||||
@@ -27,7 +26,7 @@ impl PropFilterElement {
|
|||||||
pub fn match_property(&self, property: &ContentLine) -> bool {
|
pub fn match_property(&self, property: &ContentLine) -> bool {
|
||||||
if let Some(TimeRangeElement { start, end }) = &self.time_range {
|
if let Some(TimeRangeElement { start, end }) = &self.time_range {
|
||||||
// TODO: Respect timezones
|
// TODO: Respect timezones
|
||||||
let Ok(timestamp) = CalDateTime::parse_prop(property, &HashMap::default()) else {
|
let Ok(timestamp) = CalDateTime::parse_prop(property, None) else {
|
||||||
return false;
|
return false;
|
||||||
};
|
};
|
||||||
let timestamp = timestamp.utc();
|
let timestamp = timestamp.utc();
|
||||||
@@ -62,13 +61,13 @@ impl PropFilterElement {
|
|||||||
}
|
}
|
||||||
|
|
||||||
pub fn match_component(&self, comp: &impl Component) -> bool {
|
pub fn match_component(&self, comp: &impl Component) -> bool {
|
||||||
let properties = comp.get_named_properties(&self.name);
|
let mut properties = comp.get_named_properties(&self.name);
|
||||||
if self.is_not_defined.is_some() {
|
if self.is_not_defined.is_some() {
|
||||||
return properties.is_empty();
|
return properties.next().is_none();
|
||||||
}
|
}
|
||||||
|
|
||||||
// The filter matches when one property instance matches
|
// The filter matches when one property instance matches
|
||||||
// Example where this matters: We have multiple attendees and want to match one
|
// Example where this matters: We have multiple attendees and want to match one
|
||||||
properties.iter().any(|prop| self.match_property(prop))
|
properties.any(|prop| self.match_property(prop))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,5 +1,3 @@
|
|||||||
use std::{collections::HashMap, io::BufReader};
|
|
||||||
|
|
||||||
use crate::Error;
|
use crate::Error;
|
||||||
use crate::addressbook::AddressbookResourceService;
|
use crate::addressbook::AddressbookResourceService;
|
||||||
use axum::{
|
use axum::{
|
||||||
@@ -12,6 +10,7 @@ use ical::{
|
|||||||
property::ContentLine,
|
property::ContentLine,
|
||||||
};
|
};
|
||||||
use rustical_store::{Addressbook, AddressbookStore, SubscriptionStore, auth::Principal};
|
use rustical_store::{Addressbook, AddressbookStore, SubscriptionStore, auth::Principal};
|
||||||
|
use std::io::BufReader;
|
||||||
use tracing::instrument;
|
use tracing::instrument;
|
||||||
|
|
||||||
#[instrument(skip(resource_service))]
|
#[instrument(skip(resource_service))]
|
||||||
@@ -38,7 +37,7 @@ pub async fn route_import<AS: AddressbookStore, S: SubscriptionStore>(
|
|||||||
value: Some(uuid::Uuid::new_v4().to_string()),
|
value: Some(uuid::Uuid::new_v4().to_string()),
|
||||||
params: vec![].into(),
|
params: vec![].into(),
|
||||||
});
|
});
|
||||||
card = card_mut.build(&HashMap::new()).unwrap();
|
card = card_mut.build(None).unwrap();
|
||||||
}
|
}
|
||||||
// TODO: Make nicer
|
// TODO: Make nicer
|
||||||
let uid = card.get_uid().unwrap();
|
let uid = card.get_uid().unwrap();
|
||||||
|
|||||||
@@ -56,22 +56,22 @@ impl PropFilterElement {
|
|||||||
}
|
}
|
||||||
|
|
||||||
pub fn match_component(&self, comp: &impl PropFilterable) -> bool {
|
pub fn match_component(&self, comp: &impl PropFilterable) -> bool {
|
||||||
let properties = comp.get_named_properties(&self.name);
|
let mut properties = comp.get_named_properties(&self.name);
|
||||||
if self.is_not_defined.is_some() {
|
if self.is_not_defined.is_some() {
|
||||||
return properties.is_empty();
|
return properties.next().is_none();
|
||||||
}
|
}
|
||||||
|
|
||||||
// The filter matches when one property instance matches
|
// The filter matches when one property instance matches
|
||||||
properties.iter().any(|prop| self.match_property(prop))
|
properties.any(|prop| self.match_property(prop))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub trait PropFilterable {
|
pub trait PropFilterable {
|
||||||
fn get_named_properties(&self, name: &str) -> Vec<&ContentLine>;
|
fn get_named_properties<'a>(&'a self, name: &'a str) -> impl Iterator<Item = &'a ContentLine>;
|
||||||
}
|
}
|
||||||
|
|
||||||
impl PropFilterable for AddressObject {
|
impl PropFilterable for AddressObject {
|
||||||
fn get_named_properties(&self, name: &str) -> Vec<&ContentLine> {
|
fn get_named_properties<'a>(&'a self, name: &'a str) -> impl Iterator<Item = &'a ContentLine> {
|
||||||
self.get_vcard().get_named_properties(name)
|
self.get_vcard().get_named_properties(name)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -9,7 +9,7 @@ use tower::ServiceExt;
|
|||||||
|
|
||||||
mod calendar;
|
mod calendar;
|
||||||
mod calendar_import;
|
mod calendar_import;
|
||||||
mod calendar_report;
|
// mod calendar_report;
|
||||||
|
|
||||||
#[rstest]
|
#[rstest]
|
||||||
#[tokio::test]
|
#[tokio::test]
|
||||||
|
|||||||
@@ -4,9 +4,10 @@ expression: body
|
|||||||
---
|
---
|
||||||
BEGIN:VCALENDAR
|
BEGIN:VCALENDAR
|
||||||
VERSION:2.0
|
VERSION:2.0
|
||||||
|
PRODID:RustiCal Export
|
||||||
CALSCALE:GREGORIAN
|
CALSCALE:GREGORIAN
|
||||||
PRODID:RustiCal
|
|
||||||
X-WR-CALNAME:Calendar
|
X-WR-CALNAME:Calendar
|
||||||
X-WR-CALDESC:Description
|
X-WR-CALDESC:Description
|
||||||
|
X-WR-CALCOLOR:#00FF00
|
||||||
X-WR-TIMEZONE:US/Eastern
|
X-WR-TIMEZONE:US/Eastern
|
||||||
END:VCALENDAR
|
END:VCALENDAR
|
||||||
|
|||||||
@@ -1,14 +0,0 @@
|
|||||||
---
|
|
||||||
source: src/integration_tests/caldav/calendar.rs
|
|
||||||
assertion_line: 145
|
|
||||||
expression: body
|
|
||||||
---
|
|
||||||
BEGIN:VCALENDAR
|
|
||||||
VERSION:2.0
|
|
||||||
PRODID:RustiCal Export
|
|
||||||
CALSCALE:GREGORIAN
|
|
||||||
X-WR-CALNAME:Calendar
|
|
||||||
X-WR-CALDESC:Description
|
|
||||||
X-WR-CALCOLOR:#00FF00
|
|
||||||
X-WR-TIMEZONE:US/Eastern
|
|
||||||
END:VCALENDAR
|
|
||||||
@@ -4,8 +4,8 @@ expression: body
|
|||||||
---
|
---
|
||||||
BEGIN:VCALENDAR
|
BEGIN:VCALENDAR
|
||||||
VERSION:2.0
|
VERSION:2.0
|
||||||
|
PRODID:RustiCal Export
|
||||||
CALSCALE:GREGORIAN
|
CALSCALE:GREGORIAN
|
||||||
PRODID:RustiCal
|
|
||||||
BEGIN:VEVENT
|
BEGIN:VEVENT
|
||||||
UID:[UID]
|
UID:[UID]
|
||||||
SUMMARY:One-off Meeting
|
SUMMARY:One-off Meeting
|
||||||
|
|||||||
@@ -4,8 +4,8 @@ expression: body
|
|||||||
---
|
---
|
||||||
BEGIN:VCALENDAR
|
BEGIN:VCALENDAR
|
||||||
VERSION:2.0
|
VERSION:2.0
|
||||||
|
PRODID:RustiCal Export
|
||||||
CALSCALE:GREGORIAN
|
CALSCALE:GREGORIAN
|
||||||
PRODID:RustiCal
|
|
||||||
BEGIN:VTIMEZONE
|
BEGIN:VTIMEZONE
|
||||||
LAST-MODIFIED:20040110T032845Z
|
LAST-MODIFIED:20040110T032845Z
|
||||||
TZID:US/Eastern
|
TZID:US/Eastern
|
||||||
@@ -29,7 +29,7 @@ DTSTAMP:20060206T001102Z
|
|||||||
DTSTART;TZID=US/Eastern:20060102T100000
|
DTSTART;TZID=US/Eastern:20060102T100000
|
||||||
DURATION:PT1H
|
DURATION:PT1H
|
||||||
SUMMARY:Event #1
|
SUMMARY:Event #1
|
||||||
Description:Go Steelers!
|
DESCRIPTION:Go Steelers!
|
||||||
UID:[UID]
|
UID:[UID]
|
||||||
END:VEVENT
|
END:VEVENT
|
||||||
BEGIN:VEVENT
|
BEGIN:VEVENT
|
||||||
|
|||||||
@@ -8,7 +8,7 @@ expression: body
|
|||||||
<href>/carddav/principal/user/contacts/newcard.vcf</href>
|
<href>/carddav/principal/user/contacts/newcard.vcf</href>
|
||||||
<propstat>
|
<propstat>
|
||||||
<prop>
|
<prop>
|
||||||
<getetag>"24835b6c11816c864f9edadd4c7c296234c643892afcbbc5fbf5c9b7ac935cf8"</getetag>
|
<getetag>"ea0bf4a2ce7ef84606a4cf9235776dbc11b3e7ce351ddf35f27cbc0088acca7e"</getetag>
|
||||||
<CARD:address-data>BEGIN:VCARD
|
<CARD:address-data>BEGIN:VCARD
|
||||||
VERSION:3.0
|
VERSION:3.0
|
||||||
FN:Cyrus Daboo
|
FN:Cyrus Daboo
|
||||||
|
|||||||
@@ -1,36 +0,0 @@
|
|||||||
---
|
|
||||||
source: src/integration_tests/carddav/addressbook.rs
|
|
||||||
assertion_line: 446
|
|
||||||
expression: body
|
|
||||||
---
|
|
||||||
<?xml version="1.0" encoding="utf-8"?>
|
|
||||||
<multistatus xmlns="DAV:" xmlns:CAL="urn:ietf:params:xml:ns:caldav" xmlns:CARD="urn:ietf:params:xml:ns:carddav" xmlns:CS="http://calendarserver.org/ns/" xmlns:PUSH="https://bitfire.at/webdav-push">
|
|
||||||
<response>
|
|
||||||
<href>/carddav/principal/user/contacts/newcard.vcf</href>
|
|
||||||
<propstat>
|
|
||||||
<prop>
|
|
||||||
<getetag>"ea0bf4a2ce7ef84606a4cf9235776dbc11b3e7ce351ddf35f27cbc0088acca7e"</getetag>
|
|
||||||
<CARD:address-data>BEGIN:VCARD
|
|
||||||
VERSION:3.0
|
|
||||||
FN:Cyrus Daboo
|
|
||||||
N:Daboo;Cyrus
|
|
||||||
ADR;TYPE=POSTAL:;2822 Email HQ;Suite 2821;RFCVille;PA;15213;USA
|
|
||||||
EMAIL;TYPE=INTERNET,PREF:cyrus@example.com
|
|
||||||
NICKNAME:me
|
|
||||||
NOTE:Example VCard.
|
|
||||||
ORG:Self Employed
|
|
||||||
TEL;TYPE=WORK,VOICE:412 605 0499
|
|
||||||
TEL;TYPE=FAX:412 605 0705
|
|
||||||
URL:http://www.example.com
|
|
||||||
UID:1234-5678-9000-1
|
|
||||||
END:VCARD
|
|
||||||
</CARD:address-data>
|
|
||||||
</prop>
|
|
||||||
<status>HTTP/1.1 200 OK</status>
|
|
||||||
</propstat>
|
|
||||||
</response>
|
|
||||||
<response>
|
|
||||||
<href>/home/bernard/addressbook/vcf1.vcf</href>
|
|
||||||
<status>HTTP/1.1 404 Not Found</status>
|
|
||||||
</response>
|
|
||||||
</multistatus>
|
|
||||||
Reference in New Issue
Block a user