feat(vcard): add RFC 6868 parameter value encoding
Adds application/adapters/param_encoding.rs: encode/decode for the three
RFC 6868 caret-escape sequences (^n newline, ^^ literal caret, ^' literal
DQUOTE) plus render_param_value, which quotes and encodes a parameter
value only when the vCard/iCalendar param-value grammar requires it
(comma/semicolon/colon triggers quoting; an embedded DQUOTE/caret/newline
needs escaping even once quoted).
Wires render_param_value into the two vCard generators' TYPE parameter
emission (EMAIL/TEL/ADR) in carddav_adapter.rs::contact_to_vcard and
contact_service.rs::generate_vcard — contact `type` fields are free text,
not a fixed enum, so a value containing a comma or quote previously
produced outright broken vCard syntax (no quoting/escaping was applied
at all).
Scope note: this branch only fixes the generation side. The existing
vCard parser is a naive line-by-line substring scanner (`line.contains
("TYPE=WORK")`) with no real per-parameter tokenizing, so there's no
integration point yet for the decode half without a larger parser
rewrite — that's part of the vCard 4.0 work (RFC 6350), which depends on
this branch for the shared encoding utility.
This commit is contained in:
@@ -2,6 +2,7 @@ use chrono::Utc;
|
||||
use std::sync::Arc;
|
||||
use uuid::Uuid;
|
||||
|
||||
use crate::application::adapters::param_encoding::render_param_value;
|
||||
use crate::application::dtos::address_book_dto::{
|
||||
AddressBookDto, CreateAddressBookDto, UpdateAddressBookDto,
|
||||
};
|
||||
@@ -286,8 +287,10 @@ impl ContactService {
|
||||
|
||||
// Email addresses
|
||||
for email in contact.email() {
|
||||
let mut ty = String::new();
|
||||
crate::common::fmt::push_upper(&mut ty, &email.r#type);
|
||||
vcard.push_str("EMAIL;TYPE=");
|
||||
crate::common::fmt::push_upper(&mut vcard, &email.r#type);
|
||||
vcard.push_str(&render_param_value(&ty));
|
||||
vcard.push(':');
|
||||
vcard.push_str(&email.email);
|
||||
vcard.push_str("\r\n");
|
||||
@@ -313,8 +316,10 @@ impl ContactService {
|
||||
let postal_code = addr.postal_code.as_deref().unwrap_or_default();
|
||||
let country = addr.country.as_deref().unwrap_or_default();
|
||||
|
||||
let mut ty = String::new();
|
||||
crate::common::fmt::push_upper(&mut ty, &addr.r#type);
|
||||
vcard.push_str("ADR;TYPE=");
|
||||
crate::common::fmt::push_upper(&mut vcard, &addr.r#type);
|
||||
vcard.push_str(&render_param_value(&ty));
|
||||
let _ = write!(
|
||||
vcard,
|
||||
":;;{};{};{};{};{}\r\n",
|
||||
|
||||
Reference in New Issue
Block a user