import type { QName } from "@/worker/xml/namespaces"; import { CALDAV_NS, CARDDAV_NS, DAV_NS, sameQName } from "@/worker/xml/namespaces"; export const LIVE_DAV_PROPS = [ "creationdate", "displayname", "getcontentlanguage", "getcontentlength", "getcontenttype", "getetag", "getlastmodified", "lockdiscovery", "resourcetype", "supportedlock", ] as const; // Computed/protected DAV props that are never writable as dead props on any resource. // RFC 3744 (ACL), RFC 4791 (CalDAV), RFC 6352 (CardDAV), RFC 6578 (sync). const PROTECTED_DAV_LOCAL_NAMES_ALL = new Set([ "getcontentlength", "getcontenttype", "getetag", "getlastmodified", "creationdate", "lockdiscovery", "supportedlock", "resourcetype", "supported-report-set", "sync-token", "owner", "group", "principal-collection-set", "current-user-principal", "current-user-privilege-set", "supported-privilege-set", "acl", "acl-restrictions", "inherited-acl-set", ]); const PROTECTED_CALDAV_LOCAL_NAMES = new Set([ "supported-calendar-data", "supported-calendar-component-set", "max-resource-size", "calendar-home-set", "calendar-user-address-set", "calendar-user-type", "schedule-inbox-URL", "schedule-outbox-URL", ]); const PROTECTED_CARDDAV_LOCAL_NAMES = new Set([ "supported-address-data", "max-resource-size", "addressbook-home-set", ]); export function davProp(localName: string): QName { return { nsUri: DAV_NS, localName }; } // Resource kinds for protected property policy. Collections accept displayname as a // settable property where the RFCs allow it; objects keep displayname as a live prop. export type DavResourcePropKind = | "file-resource" | "calendar-home" | "calendar-collection" | "calendar-object" | "addressbook-home" | "addressbook-collection" | "addressbook-object"; export function isProtectedLivePropForResource(prop: QName, kind: DavResourcePropKind): boolean { if (prop.nsUri === DAV_NS) { if (PROTECTED_DAV_LOCAL_NAMES_ALL.has(prop.localName)) return true; // RFC 4791 4.2 / RFC 6352 5.2: displayname is mutable on calendar and address book // collections; on file resources and objects, treat it as protected like other live props. if (prop.localName === "displayname") { return ( kind === "file-resource" || kind === "calendar-object" || kind === "addressbook-object" || kind === "calendar-home" || kind === "addressbook-home" ); } return false; } if (prop.nsUri === CALDAV_NS) return PROTECTED_CALDAV_LOCAL_NAMES.has(prop.localName); if (prop.nsUri === CARDDAV_NS) return PROTECTED_CARDDAV_LOCAL_NAMES.has(prop.localName); return false; } export function includesProp(props: QName[], wanted: QName): boolean { return props.some((prop) => sameQName(prop, wanted)); } export function defaultAllpropNames(): QName[] { return LIVE_DAV_PROPS.map((name) => davProp(name)); }