1 /* http_dav.h -- Routines for dealing with DAV properties in httpd
2  *
3  * Copyright (c) 1994-2011 Carnegie Mellon University.  All rights reserved.
4  *
5  * Redistribution and use in source and binary forms, with or without
6  * modification, are permitted provided that the following conditions
7  * are met:
8  *
9  * 1. Redistributions of source code must retain the above copyright
10  *    notice, this list of conditions and the following disclaimer.
11  *
12  * 2. Redistributions in binary form must reproduce the above copyright
13  *    notice, this list of conditions and the following disclaimer in
14  *    the documentation and/or other materials provided with the
15  *    distribution.
16  *
17  * 3. The name "Carnegie Mellon University" must not be used to
18  *    endorse or promote products derived from this software without
19  *    prior written permission. For permission or any legal
20  *    details, please contact
21  *      Carnegie Mellon University
22  *      Center for Technology Transfer and Enterprise Creation
23  *      4615 Forbes Avenue
24  *      Suite 302
25  *      Pittsburgh, PA  15213
26  *      (412) 268-7393, fax: (412) 268-7395
27  *      innovation@andrew.cmu.edu
28  *
29  * 4. Redistributions of any form whatsoever must retain the following
30  *    acknowledgment:
31  *    "This product includes software developed by Computing Services
32  *     at Carnegie Mellon University (http://www.cmu.edu/computing/)."
33  *
34  * CARNEGIE MELLON UNIVERSITY DISCLAIMS ALL WARRANTIES WITH REGARD TO
35  * THIS SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
36  * AND FITNESS, IN NO EVENT SHALL CARNEGIE MELLON UNIVERSITY BE LIABLE
37  * FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
38  * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN
39  * AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING
40  * OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
41  *
42  */
43 
44 #ifndef HTTP_DAV_H
45 #define HTTP_DAV_H
46 
47 #include <stdint.h>
48 #include <libical/ical.h>
49 #include <libxml/tree.h>
50 
51 #include "acl.h"
52 #include "annotate.h"
53 #include "caldav_db.h"
54 #include "httpd.h"
55 #include "spool.h"
56 #include "quota.h"
57 #include "strarray.h"
58 
59 #define NULL_ETAG       "da39a3ee5e6b4b0d3255bfef95601890afd80709"
60                         /* SHA1("") */
61 
62 #define SERVER_INFO     ".server-info"
63 #define SCHED_INBOX     "Inbox/"
64 #define SCHED_OUTBOX    "Outbox/"
65 #define SCHED_DEFAULT   "Default/"
66 #define MANAGED_ATTACH  "Attachments/"
67 
68 /* XML namespace URIs */
69 #define XML_NS_DAV      "DAV:"
70 #define XML_NS_CALDAV   "urn:ietf:params:xml:ns:caldav"
71 #define XML_NS_CARDDAV  "urn:ietf:params:xml:ns:carddav"
72 #define XML_NS_ISCHED   "urn:ietf:params:xml:ns:ischedule"
73 #define XML_NS_CS       "http://calendarserver.org/ns/"
74 #define XML_NS_MECOM    "http://me.com/_namespace/"
75 #define XML_NS_MOBME    "urn:mobileme:davservices"
76 #define XML_NS_APPLE    "http://apple.com/ns/ical/"
77 #define XML_NS_USERFLAG "http://cyrusimap.org/ns/userflag/"
78 #define XML_NS_SYSFLAG  "http://cyrusimap.org/ns/sysflag/"
79 #define XML_NS_DAVMOUNT "http://purl.org/NET/webdav/mount/"
80 
81 #define USER_COLLECTION_PREFIX  "user"
82 #define GROUP_COLLECTION_PREFIX "group"
83 
84 #define LOCK_TOKEN_URL_SCHEME "urn:uuid:"
85 #define SYNC_TOKEN_URL_SCHEME "data:,"
86 
87 #define SHARED_COLLECTION_DELIM '.'
88 
89 /* Index into known namespace array */
90 enum {
91     NS_REQ_ROOT = -1,   /* special case: ns of request root (not an index) */
92     NS_DAV,
93     NS_CALDAV,
94     NS_CARDDAV,
95     NS_ISCHED,
96     NS_CS,
97     NS_MECOM,
98     NS_MOBME,
99     NS_CYRUS,
100 };
101 #define NUM_NAMESPACE 8
102 
103 /* Cyrus-specific privileges */
104 #define DACL_PROPCOL    ACL_WRITE       /* CY:write-properties-collection */
105 #define DACL_PROPRSRC   ACL_ANNOTATEMSG /* CY:write-properties-resource */
106 #define DACL_MKCOL      ACL_CREATE      /* CY:make-collection */
107 #define DACL_ADDRSRC    ACL_POST        /* CY:add-resource */
108 #define DACL_RMCOL      ACL_DELETEMBOX  /* CY:remove-collection */
109 #define DACL_RMRSRC     (ACL_DELETEMSG\
110                          |ACL_EXPUNGE)  /* CY:remove-resource */
111 #define DACL_ADMIN      ACL_ADMIN       /* CY:admin (aggregates
112                                            DAV:read-acl, DAV:write-acl,
113                                            DAV:unlock and DAV:share) */
114 
115 /* WebDAV (RFC 3744) privileges */
116 #define DACL_READ       (ACL_READ\
117                          |ACL_LOOKUP)   /* DAV:read (aggregates
118                                            DAV:read-current-user-privilege-set
119                                            and CALDAV:read-free-busy) */
120 #define DACL_WRITECONT  ACL_INSERT      /* DAV:write-content */
121 #define DACL_WRITEPROPS (DACL_PROPCOL\
122                          |DACL_PROPRSRC)/* DAV:write-properties */
123 #define DACL_BIND       (DACL_MKCOL\
124                          |DACL_ADDRSRC) /* DAV:bind */
125 #define DACL_UNBIND     (DACL_RMCOL\
126                          |DACL_RMRSRC)  /* DAV:unbind */
127 #define DACL_WRITE      (DACL_WRITECONT\
128                          |DACL_WRITEPROPS\
129                          |DACL_BIND\
130                          |DACL_UNBIND)  /* DAV:write */
131 #define DACL_ALL        (DACL_READ\
132                          |DACL_WRITE\
133                          |DACL_ADMIN)   /* DAV:all */
134 
135 /* CalDAV (RFC 4791) privileges */
136 #define DACL_READFB     ACL_USER9       /* CALDAV:read-free-busy
137                                            (implicit if user has DAV:read) */
138 
139 /* CalDAV Scheduling (RFC 6638) privileges
140 
141    We use the same ACLs for both schedule-deliver* and schedule-send* because
142    functionality of Scheduling Inbox and Outbox are mutually exclusive.
143    We use ACL_USER9 for both read-free-busy and schedule-*-freebusy because
144    Scheduling Inbox and Outbox don't contribute to free-busy.
145 */
146 #define DACL_SCHEDFB    ACL_USER9       /* For Scheduling Inbox:
147                                            CALDAV:schedule-query-freebusy
148 
149                                            For Scheduling Outbox:
150                                            CALDAV:schedule-send-freebusy */
151 #define DACL_INVITE     ACL_USER8       /* For Scheduling Inbox:
152                                            CALDAV:schedule-deliver-invite
153 
154                                            For Scheduling Outbox:
155                                            CALDAV:schedule-send-invite */
156 #define DACL_REPLY      ACL_USER7       /* For Scheduling Inbox:
157                                            CALDAV:schedule-deliver-reply
158 
159                                            For Scheduling Outbox:
160                                            CALDAV:schedule-send-reply */
161 #define DACL_SCHED      (DACL_SCHEDFB\
162                          |DACL_INVITE\
163                          |DACL_REPLY)   /* For Scheduling Inbox:
164                                            CALDAV:schedule-deliver (aggregates
165                                            CALDAV:schedule-deliver-invite,
166                                            schedule-deliver-reply,
167                                            schedule-query-freebusy);
168 
169                                            For Scheduling Outbox:
170                                            CALDAV:schedule-send (aggregates
171                                            CALDAV:schedule-send-invite,
172                                            schedule-send-reply,
173                                            schedule-send-freebusy) */
174 
175 /* Index into preconditions array */
176 enum {
177     /* WebDAV (RFC 4918) preconditions */
178     DAV_PROT_PROP = 1,
179     DAV_BAD_LOCK_TOKEN,
180     DAV_NEED_LOCK_TOKEN,
181     DAV_LOCKED,
182     DAV_FINITE_DEPTH,
183 
184     /* WebDAV Versioning (RFC 3253) preconditions */
185     DAV_SUPP_REPORT,
186     DAV_RES_EXISTS,
187 
188     /* WebDAV ACL (RFC 3744) preconditions */
189     DAV_NEED_PRIVS,
190     DAV_NO_INVERT,
191     DAV_NO_ABSTRACT,
192     DAV_SUPP_PRIV,
193     DAV_RECOG_PRINC,
194     DAV_ALLOW_PRINC,
195     DAV_GRANT_ONLY,
196 
197     /* WebDAV Quota (RFC 4331) preconditions */
198     DAV_OVER_QUOTA,
199     DAV_NO_DISK_SPACE,
200 
201     /* WebDAV Extended MKCOL (RFC 5689) preconditions */
202     DAV_VALID_RESTYPE,
203 
204     /* WebDAV Sync (RFC 6578) preconditions */
205     DAV_SYNC_TOKEN,
206     DAV_OVER_LIMIT,
207 
208     /* CalDAV (RFC 4791) preconditions */
209     CALDAV_SUPP_DATA,
210     CALDAV_VALID_DATA,
211     CALDAV_VALID_OBJECT,
212     CALDAV_SUPP_COMP,
213     CALDAV_LOCATION_OK,
214     CALDAV_UID_CONFLICT,
215     CALDAV_SUPP_FILTER,
216     CALDAV_VALID_FILTER,
217     CALDAV_SUPP_COLLATION,
218 
219     /* RSCALE (RFC 7529) preconditions */
220     CALDAV_SUPP_RSCALE,
221 
222     /* Time Zones by Reference (RFC 7809) preconditions */
223     CALDAV_VALID_TIMEZONE,
224 
225     /* Managed Attachments (draft-ietf-calext-caldav-attachments) preconditions */
226     CALDAV_VALID_MANAGEDID,
227 
228     /* Bulk Change (draft-daboo-calendarserver-bulk-change) preconditions */
229     CALDAV_CTAG_OK,
230 
231     /* CalDAV Scheduling (RFC 6638) preconditions */
232     CALDAV_VALID_SCHED,
233     CALDAV_VALID_ORGANIZER,
234     CALDAV_UNIQUE_OBJECT,
235     CALDAV_SAME_ORGANIZER,
236     CALDAV_ALLOWED_ORG_CHANGE,
237     CALDAV_ALLOWED_ATT_CHANGE,
238     CALDAV_DEFAULT_NEEDED,
239     CALDAV_VALID_DEFAULT,
240 
241     /* iSchedule (draft-desruisseaux-ischedule) preconditions */
242     ISCHED_UNSUPP_VERSION,
243     ISCHED_UNSUPP_DATA,
244     ISCHED_INVALID_DATA,
245     ISCHED_INVALID_SCHED,
246     ISCHED_ORIG_MISSING,
247     ISCHED_MULTIPLE_ORIG,
248     ISCHED_ORIG_INVALID,
249     ISCHED_ORIG_DENIED,
250     ISCHED_RECIP_MISSING,
251     ISCHED_RECIP_MISMATCH,
252     ISCHED_VERIFICATION_FAILED,
253 
254     /* CardDAV (RFC 6352) preconditions */
255     CARDDAV_SUPP_DATA,
256     CARDDAV_VALID_DATA,
257     CARDDAV_UID_CONFLICT,
258     CARDDAV_LOCATION_OK,
259     CARDDAV_SUPP_FILTER,
260     CARDDAV_SUPP_COLLATION
261 };
262 
263 /* Preference bits */
264 enum {
265     PREFER_MIN    = (1<<0),
266     PREFER_REP    = (1<<1),
267     PREFER_NOROOT = (1<<2)
268 };
269 
270 #define NO_DUP_CHECK (1<<7)
271 
272 /* PROPFIND modes */
273 enum {
274     PROPFIND_NONE = 0,                  /* only used with REPORT */
275     PROPFIND_ALL,
276     PROPFIND_NAME,
277     PROPFIND_PROP,
278     PROPFIND_EXPAND                     /* only used with expand-prop REPORT */
279 };
280 
281 
282 extern struct meth_params princ_params;
283 
284 /* Function to fetch resource validators */
285 typedef int (*get_validators_t)(struct mailbox *mailbox, void *data,
286                                 const char *userid, struct index_record *record,
287                                 const char **etag, time_t *lastmod);
288 
289 /* Function to fetch resource modseq */
290 typedef modseq_t (*get_modseq_t)(struct mailbox *mailbox,
291                                  void *data, const char *userid);
292 
293 typedef void *(*db_open_proc_t)(struct mailbox *mailbox);
294 typedef int (*db_close_proc_t)(void *davdb);
295 
296 /* Function to lookup DAV 'resource' in 'mailbox',
297  * placing the record in 'data'
298  */
299 typedef int (*db_lookup_proc_t)(void *davdb, const char *mailbox,
300                                 const char *resource, void **data,
301                                 int tombstones);
302 
303 /* Function to lookup DAV 'imapuid' in 'mailbox',
304  * placing the record in 'data'
305  */
306 typedef int (*db_imapuid_proc_t)(void *davdb, const char *mailbox,
307                                  int uid, void **data, int tombstones);
308 
309 /* Function to process each DAV resource in 'mailbox' with 'cb' */
310 typedef int (*db_foreach_proc_t)(void *davdb, const char *mailbox,
311                                  int (*cb)(void *rock, void *data), void *rock);
312 
313 /* Function to process 'limit' DAV resources
314    updated since 'oldmodseq' in 'mailbox' with 'cb' */
315 typedef int (*db_updates_proc_t)(void *davdb, modseq_t oldmodseq,
316                                  const char *mailbox, int kind, int limit,
317                                  int (*cb)(void *rock, void *data), void *rock);
318 
319 /* Context for fetching properties */
320 struct propfind_entry_list;
321 struct prop_entry;
322 struct error_t;
323 
324 /* Propfind return flags */
325 struct fctx_flags_t {
326     unsigned long fetcheddata : 1;      /* Did we fetch iCalendar/vCard data? */
327     unsigned long cs_sharing  : 1;      /* Is client using CS sharing? */
328 };
329 
330 struct propfind_ctx {
331     struct transaction_t *txn;          /* request transaction */
332     struct request_target_t *req_tgt;   /* parsed target URL */
333     unsigned mode;                      /* none, allprop, propname, prop */
334     unsigned depth;                     /* 0 = root, 1 = calendar, 2 = resrc */
335     unsigned prefer;                    /* bitmask of client preferences */
336     const char *userid;                 /* userid client has logged in as */
337     int userisadmin;                    /* is userid an admin */
338     struct auth_state *authstate;       /* authorization state for userid */
339     void *davdb;                        /* DAV DB corresponding to collection */
340     const mbentry_t *mbentry;           /* mbentry corresponding to collection */
341     struct mailbox *mailbox;            /* mailbox corresponding to collection */
342     struct quota quota;                 /* quota info for collection */
343     struct index_record *record;        /* cyrus.index record for resource */
344     void *data;                         /* DAV record for resource */
345     get_validators_t get_validators;    /* fetch resource validators */
346     struct buf msg_buf;                 /* mmap()'d resource file */
347     void *obj;                          /* parsed resource */
348     void (*free_obj)(void *);           /* free parsed object */
349     unsigned long reqd_privs;           /* privileges req'd on collections */
350     int (*filter)(struct propfind_ctx *,
351                   void *data);          /* callback to filter resources */
352     void *filter_crit;                  /* criteria to filter resources */
353     db_open_proc_t open_db;             /* open DAV DB for a given mailbox */
354     db_close_proc_t close_db;           /* close DAV DB for a given mailbox */
355     db_lookup_proc_t lookup_resource;   /* lookup a specific resource */
356     db_foreach_proc_t foreach_resource; /* process all resources in a mailbox */
357     int (*proc_by_resource)(void *rock, /* Callback to process a resource */
358                             void *data);
359     struct propfind_entry_list *elist;  /* List of props to fetch w/callbacks */
360     const struct prop_entry *lprops;    /* Array of known "live" properties */
361     xmlNodePtr root;                    /* root node to add to XML tree */
362     xmlNsPtr *ns;                       /* Array of our known namespaces */
363     struct hash_table *ns_table;        /* Table of all ns attached to resp */
364     unsigned prefix_count;              /* Count of new ns added to resp */
365     int *ret;                           /* Return code to pass up to caller */
366     struct fctx_flags_t flags;          /* Return flags for this propfind */
367     struct buf buf;                     /* Working buffer */
368     xmlBufferPtr xmlbuf;                /* Buffer for dumping XML nodes */
369 };
370 
371 
372 /* Context for patching (writing) properties */
373 struct proppatch_ctx {
374     struct transaction_t *txn;          /* request transaction */
375     struct mailbox *mailbox;            /* mailbox related to the collection */
376     struct index_record *record;        /* record of the specific resource */
377     const struct prop_entry *lprops;    /* Array of known "live" properties */
378     xmlNodePtr root;                    /* root node to add to XML tree */
379     xmlNsPtr *ns;                       /* Array of our supported namespaces */
380     struct txn *tid;                    /* Transaction ID for annot writes */
381     int *ret;                           /* Return code to pass up to caller */
382     struct buf buf;                     /* Working buffer */
383 };
384 
385 
386 /* Structure for property status */
387 struct propstat {
388     xmlNodePtr root;
389     long status;
390     unsigned precond;
391 };
392 
393 /* Index into propstat array */
394 enum {
395     PROPSTAT_OK = 0,
396     PROPSTAT_UNAUTH,
397     PROPSTAT_FORBID,
398     PROPSTAT_NOTFOUND,
399     PROPSTAT_CONFLICT,
400     PROPSTAT_FAILEDDEP,
401     PROPSTAT_ERROR,
402     PROPSTAT_OVERQUOTA
403 };
404 #define NUM_PROPSTAT 8
405 
406 
407 /* Context for "live" properties */
408 struct prop_entry {
409     const char *name;                   /* Property name */
410     unsigned ns;                        /* Property namespace */
411     unsigned char flags;                /* Flags for how/where props apply */
412     int (*get)(const xmlChar *name,     /* Callback to fetch property */
413                xmlNsPtr ns, struct propfind_ctx *fctx, xmlNodePtr prop,
414                xmlNodePtr resp, struct propstat *propstat, void *rock);
415     int (*put)(xmlNodePtr prop,         /* Callback to write property */
416                unsigned set, struct proppatch_ctx *pctx,
417                struct propstat *propstat, void *rock);
418     void *rock;                         /* Add'l data to pass to callback */
419 };
420 
421 /* Bitmask of property flags */
422 enum {
423     PROP_ALLPROP =      (1<<0),         /* Returned in <allprop> request */
424     PROP_COLLECTION =   (1<<1),         /* Returned for collection */
425     PROP_RESOURCE =     (1<<2),         /* Returned for resource */
426     PROP_PERUSER =      (1<<3),         /* Per-user property */
427     PROP_PRESCREEN =    (1<<4),         /* Prescreen property using callback */
428     PROP_CLEANUP =      (1<<5)          /* Cleanup property using callback */
429 };
430 
431 
432 /* Function to check headers for preconditions */
433 struct meth_params;
434 typedef int (*check_precond_t)(struct transaction_t *txn,
435                                struct meth_params *params,
436                                struct mailbox *mailbox, const void *data,
437                                const char *etag, time_t lastmod);
438 
439 /* Function to insert/update DAV resource in 'data' */
440 typedef int (*db_write_proc_t)(void *davdb, void *data);
441 
442 /* Function to delete resource in 'rowid' */
443 typedef int (*db_delete_proc_t)(void *davdb, unsigned rowid);
444 
445 typedef int (*db_proc_t)(void *davdb);
446 
447 struct davdb_params {
448     db_open_proc_t open_db;             /* open DAV DB for a given mailbox */
449     db_close_proc_t close_db;           /* close DAV DB for a given mailbox */
450     db_proc_t begin_transaction;
451     db_proc_t commit_transaction;
452     db_proc_t abort_transaction;
453     db_lookup_proc_t lookup_resource;   /* lookup a specific resource */
454     db_imapuid_proc_t lookup_imapuid;   /* lookup a specific resource */
455     db_foreach_proc_t foreach_resource; /* process all resources in a mailbox */
456     db_updates_proc_t foreach_update;   /* process updated resources in a mbox */
457     /* XXX - convert these to lock management only.  For everything else,
458      * we need to go via mailbox.c for replication support */
459     db_write_proc_t write_resourceLOCKONLY;     /* write a specific resource */
460     db_delete_proc_t delete_resourceLOCKONLY;   /* delete a specific resource */
461 };
462 
463 /*
464  * Process 'priv', augmenting 'rights' as necessary.
465  * Returns 1 if processing is complete.
466  * Returns 0 if processing should continue in meth_acl()
467  */
468 typedef int (*acl_proc_t)(struct transaction_t *txn, xmlNodePtr priv,
469                           int *rights);
470 
471 /* Function to do special processing for DELETE method (optional) */
472 typedef int (*delete_proc_t)(struct transaction_t *txn, struct mailbox *mailbox,
473                              struct index_record *record, void *data);
474 
475 /* Function to do special processing for GET method (optional) */
476 typedef int (*get_proc_t)(struct transaction_t *txn, struct mailbox *mailbox,
477                           struct index_record *record, void *data, void **obj);
478 
479 /* Function to convert to/from MIME type */
480 struct mime_type_t {
481     const char *content_type;
482     const char *version;
483     const char *file_ext;
484     struct buf* (*from_object)(void *);
485     void* (*to_object)(const struct buf *);
486     void (*free)(void *);
487     const char* (*begin_stream)(struct buf *, struct mailbox *mailbox,
488                                 const char *prodid, const char *name,
489                                 const char *desc, const char *color);
490     void (*end_stream)(struct buf *);
491 };
492 
493 /* meth_mkcol() parameters */
494 typedef int (*mkcol_proc_t)(struct mailbox *mailbox);
495 
496 struct mkcol_params {
497     unsigned location_precond;          /* precond code for bad location */
498     uint32_t mbtype;                    /* mailbox type collection */
499     mkcol_proc_t proc;                  /* func to do post-create processing */
500 };
501 
502 /*
503  * Function to do special processing for POST method (optional).
504  * Returns HTTP_CONTINUE if processing should continue in meth_post(),
505  * otherwise processing is complete.
506  */
507 typedef int (*post_proc_t)(struct transaction_t *txn);
508 
509 typedef int (*import_proc_t)(struct transaction_t *txn, void *obj,
510                              struct mailbox *mailbox, void *davdb,
511                              xmlNodePtr root, xmlNsPtr *ns, unsigned flags);
512 
513 /* POST "mode" bits */
514 enum {
515     POST_ADDMEMBER = (1<<0),
516     POST_SHARE     = (1<<1)
517 };
518 
519 /* meth_put() parameters */
520 typedef int (*put_proc_t)(struct transaction_t *txn, void *obj,
521                           struct mailbox *mailbox, const char *resource,
522                           void *davdb, unsigned flags);
523 
524 struct copy_params {
525     unsigned uid_conf_precond;          /* precond code for UID conflict */
526     put_proc_t proc;                    /* function to process & COPY a rsrc */
527 };
528 
529 struct post_params {
530     unsigned allowed;                   /* allowed generic POST "modes" */
531     post_proc_t proc;                   /* special POST handling (optional) */
532     struct {
533         unsigned data_ns;               /* namespace of "data" property */
534         const char *data_prop;          /* name of "data" prop for CRUD (opt) */
535         import_proc_t import;           /* func to import multiple rsrcs (opt) */
536     } bulk;
537 };
538 
539 struct put_params {
540     unsigned supp_data_precond;         /* precond code for unsupported data */
541     put_proc_t proc;                    /* function to process & PUT a rsrc */
542 };
543 
544 struct propfind_params {
545     unsigned finite_depth_precond;      /* precond code for finite depth */
546     const struct prop_entry *lprops;    /* array of "live" properties */
547 };
548 
549 /* meth_report() parameters */
550 typedef int (*report_proc_t)(struct transaction_t *txn,
551                              struct meth_params *rparams,
552                              xmlNodePtr inroot, struct propfind_ctx *fctx);
553 
554 struct report_type_t {
555     const char *name;                   /* report name */
556     unsigned ns;                        /* report namespace */
557     const char *resp_root;              /* name of XML root element in resp */
558     report_proc_t proc;                 /* function to generate the report */
559     unsigned long reqd_privs;           /* privileges required to run report */
560     unsigned flags;                     /* report-specific flags */
561 };
562 
563 /* Report flags */
564 enum {
565     REPORT_NEED_MBOX    = (1<<0),
566     REPORT_NEED_PROPS   = (1<<1),
567     REPORT_ALLOW_PROPS  = (1<<2),
568     REPORT_DEPTH_ZERO   = (1<<3)
569 };
570 
571 /* Overwrite flags */
572 enum {
573     OVERWRITE_NO = 0,
574     OVERWRITE_YES
575 };
576 
577 struct meth_params {
578     struct mime_type_t *mime_types;     /* array of MIME types and conv funcs */
579     parse_path_t parse_path;            /* parse URI path & generate mboxname */
580     get_validators_t get_validators;    /* fetch resource validators */
581     get_modseq_t get_modseq;            /* fetch resource modseq */
582     check_precond_t check_precond;      /* check headers for preconditions */
583     struct davdb_params davdb;          /* DAV DB access functions */
584     acl_proc_t acl_ext;                 /* special ACL handling (extensions) */
585     struct copy_params copy;            /* params for copying a resource */
586     delete_proc_t delete;               /* special DELETE handling (optional) */
587     get_proc_t get;                     /* special GET handling (optional) */
588     struct mkcol_params mkcol;          /* params for creating new collection */
589     struct patch_doc_t *patch_docs;     /* array of patch docs & funcs (opt) */
590     struct post_params post;            /* params for POST handling */
591     struct put_params put;              /* params for putting a resource */
592     struct propfind_params propfind;    /* params for finding properties */
593     const struct report_type_t *reports;/* array of reports & proc functions */
594 };
595 
596 extern struct meth_params webdav_params;
597 
598 enum {
599     MATCH_TYPE_CONTAINS = 0,
600     MATCH_TYPE_EQUALS,
601     MATCH_TYPE_PREFIX,
602     MATCH_TYPE_SUFFIX
603 };
604 
605 struct match_type_t {
606     const char *name;
607     unsigned value;
608 };
609 
610 extern const struct match_type_t dav_match_types[];
611 
612 enum {
613     COLLATION_UNICODE = 0,
614     COLLATION_ASCII,
615     COLLATION_OCTET
616 };
617 
618 struct collation_t {
619     const char *name;
620     unsigned value;
621 };
622 
623 extern const struct collation_t dav_collations[];
624 
625 struct text_match_t {
626     xmlChar *text;
627     unsigned negate    : 1;
628     unsigned type      : 3;
629     unsigned collation : 3;
630     struct text_match_t *next;
631 };
632 
633 struct param_filter {
634     xmlChar *name;
635     unsigned kind;
636     unsigned not_defined : 1;
637     struct text_match_t *match;
638     struct param_filter *next;
639 };
640 
641 struct prop_filter {
642     xmlChar *name;
643     unsigned kind;
644     unsigned allof       : 1;
645     unsigned not_defined : 1;
646     void *other;                /* some other filter defined by caller */
647     struct text_match_t *match;
648     struct param_filter *param;
649     struct prop_filter *next;
650 };
651 
652 struct filter_profile_t {
653     unsigned allof      : 1;
654     unsigned collation  : 3;
655     unsigned filter_precond;
656     unsigned collation_precond;
657     unsigned (*prop_string_to_kind)(const char *);
658     unsigned no_prop_value;
659     unsigned (*param_string_to_kind)(const char *);
660     unsigned no_param_value;
661     void (*parse_propfilter)(xmlNodePtr, struct prop_filter *,
662                              struct error_t *);
663 };
664 
665 #define DAV_FILTER_ISNOTDEF_ERR \
666     "is-not-defined can NOT be combined with other elements"
667 
668 void dav_get_synctoken(struct mailbox *mailbox,
669                        struct buf *buf, const char *prefix);
670 
671 void dav_parse_propfilter(xmlNodePtr root, struct prop_filter **prop,
672                           struct filter_profile_t *profile,
673                           struct error_t *error);
674 void dav_free_propfilter(struct prop_filter *prop);
675 int dav_apply_textmatch(xmlChar *text, struct text_match_t *match);
676 
677 int report_expand_prop(struct transaction_t *txn, struct meth_params *rparams,
678                        xmlNodePtr inroot, struct propfind_ctx *fctx);
679 int report_acl_prin_prop(struct transaction_t *txn, struct meth_params *rparams,
680                          xmlNodePtr inroot, struct propfind_ctx *fctx);
681 int report_multiget(struct transaction_t *txn, struct meth_params *rparams,
682                     xmlNodePtr inroot, struct propfind_ctx *fctx);
683 int report_sync_col(struct transaction_t *txn, struct meth_params *rparams,
684                     xmlNodePtr inroot, struct propfind_ctx *fctx);
685 
686 
687 unsigned long calcarddav_allow_cb(struct request_target_t *tgt);
688 int dav_parse_req_target(struct transaction_t *txn,
689                          struct meth_params *params);
690 int calcarddav_parse_path(const char *path, struct request_target_t *tgt,
691                           const char *mboxprefix, const char **resultstr);
692 int dav_get_validators(struct mailbox *mailbox, void *data,
693                        const char *userid, struct index_record *record,
694                        const char **etag, time_t *lastmod);
695 modseq_t dav_get_modseq(struct mailbox *mailbox,
696                         void *data, const char *userid);
697 int dav_check_precond(struct transaction_t *txn, struct meth_params *params,
698                       struct mailbox *mailbox, const void *data,
699                       const char *etag, time_t lastmod);
700 int dav_store_resource(struct transaction_t *txn,
701                        const char *data, size_t datalen,
702                        struct mailbox *mailbox, struct index_record *oldrecord,
703                        modseq_t createdmodseq, strarray_t *imapflags);
704 int dav_premethod(struct transaction_t *txn);
705 unsigned get_preferences(struct transaction_t *txn);
706 struct mime_type_t *get_accept_type(const char **hdr, struct mime_type_t *types);
707 
708 int parse_xml_body(struct transaction_t *txn, xmlNodePtr *root,
709                    const char *mimetype);
710 
711 size_t make_collection_url(struct buf *buf, const char *urlprefix, int haszzzz,
712                            const mbname_t *mbname, const char *userid);
713 
714 /* Initialize an XML tree */
715 xmlNodePtr init_xml_response(const char *resp, int ns,
716                              xmlNodePtr req, xmlNsPtr *respNs);
717 
718 xmlNodePtr xml_add_href(xmlNodePtr parent, xmlNsPtr ns, const char *href);
719 xmlNodePtr xml_add_error(xmlNodePtr root, struct error_t *err,
720                          xmlNsPtr *avail_ns);
721 xmlNodePtr xml_add_prop(long status, xmlNsPtr davns,
722                         struct propstat *propstat,
723                         const xmlChar *name, xmlNsPtr ns,
724                         xmlChar *content, unsigned precond);
725 void xml_add_lockdisc(xmlNodePtr node, const char *path, struct dav_data *data);
726 int ensure_ns(xmlNsPtr *respNs, int ns, xmlNodePtr node,
727               const char *url, const char *prefix);
728 
729 int xml_add_response(struct propfind_ctx *fctx, long code, unsigned precond,
730                      const char *desc, const char *location);
731 int propfind_by_resource(void *rock, void *data);
732 int propfind_by_collection(const mbentry_t *mbentry, void *rock);
733 int expand_property(xmlNodePtr inroot, struct propfind_ctx *fctx,
734                     struct namespace_t *namespace, const char *href,
735                     parse_path_t parse_path, const struct prop_entry *lprops,
736                     xmlNodePtr root, int depth);
737 
738 int preload_proplist(xmlNodePtr proplist, struct propfind_ctx *fctx);
739 void free_entry_list(struct propfind_entry_list *elist);
740 
741 /* DAV method processing functions */
742 int meth_acl(struct transaction_t *txn, void *params);
743 int meth_copy_move(struct transaction_t *txn, void *params);
744 int meth_delete(struct transaction_t *txn, void *params);
745 int meth_get_head(struct transaction_t *txn, void *params);
746 int meth_lock(struct transaction_t *txn, void *params);
747 int meth_mkcol(struct transaction_t *txn, void *params);
748 int meth_propfind(struct transaction_t *txn, void *params);
749 int meth_proppatch(struct transaction_t *txn, void *params);
750 int meth_patch(struct transaction_t *txn, void *params);
751 int meth_post(struct transaction_t *txn, void *params);
752 int meth_put(struct transaction_t *txn, void *params);
753 int meth_report(struct transaction_t *txn, void *params);
754 int meth_unlock(struct transaction_t *txn, void *params);
755 
756 
757 /* PROPFIND callbacks */
758 
759 int propfind_getdata(const xmlChar *name, xmlNsPtr ns,
760                      struct propfind_ctx *fctx,
761                      xmlNodePtr prop, struct propstat propstat[],
762                      struct mime_type_t *mime_types,
763                      struct mime_type_t **out_type,
764                      const char *data, unsigned long datalen);
765 int propfind_fromdb(const xmlChar *name, xmlNsPtr ns,
766                     struct propfind_ctx *fctx,
767                     xmlNodePtr prop, xmlNodePtr resp,
768                     struct propstat propstat[], void *rock);
769 int propfind_fromhdr(const xmlChar *name, xmlNsPtr ns,
770                      struct propfind_ctx *fctx,
771                      xmlNodePtr prop, xmlNodePtr resp,
772                      struct propstat propstat[], void *rock);
773 int propfind_creationdate(const xmlChar *name, xmlNsPtr ns,
774                           struct propfind_ctx *fctx,
775                           xmlNodePtr prop, xmlNodePtr resp,
776                           struct propstat propstat[], void *rock);
777 int propfind_collectionname(const xmlChar *name, xmlNsPtr ns,
778                             struct propfind_ctx *fctx,
779                             xmlNodePtr prop, xmlNodePtr resp,
780                             struct propstat propstat[], void *rock);
781 int propfind_getlength(const xmlChar *name, xmlNsPtr ns,
782                        struct propfind_ctx *fctx,
783                        xmlNodePtr prop, xmlNodePtr resp,
784                        struct propstat propstat[], void *rock);
785 int propfind_getetag(const xmlChar *name, xmlNsPtr ns,
786                      struct propfind_ctx *fctx,
787                      xmlNodePtr prop, xmlNodePtr resp,
788                      struct propstat propstat[], void *rock);
789 int propfind_getlastmod(const xmlChar *name, xmlNsPtr ns,
790                         struct propfind_ctx *fctx,
791                         xmlNodePtr prop, xmlNodePtr resp,
792                         struct propstat propstat[], void *rock);
793 int propfind_lockdisc(const xmlChar *name, xmlNsPtr ns,
794                       struct propfind_ctx *fctx,
795                       xmlNodePtr prop, xmlNodePtr resp,
796                       struct propstat propstat[], void *rock);
797 int propfind_suplock(const xmlChar *name, xmlNsPtr ns,
798                      struct propfind_ctx *fctx,
799                      xmlNodePtr prop, xmlNodePtr resp,
800                      struct propstat propstat[], void *rock);
801 
802 int propfind_reportset(const xmlChar *name, xmlNsPtr ns,
803                        struct propfind_ctx *fctx,
804                        xmlNodePtr prop, xmlNodePtr resp,
805                        struct propstat propstat[], void *rock);
806 
807 int propfind_methodset(const xmlChar *name, xmlNsPtr ns,
808                        struct propfind_ctx *fctx,
809                        xmlNodePtr prop, xmlNodePtr,
810                        struct propstat propstat[], void *rock);
811 
812 int propfind_collationset(const xmlChar *name, xmlNsPtr ns,
813                           struct propfind_ctx *fctx,
814                           xmlNodePtr prop, xmlNodePtr resp,
815                           struct propstat propstat[], void *rock);
816 
817 int propfind_principalurl(const xmlChar *name, xmlNsPtr ns,
818                           struct propfind_ctx *fctx,
819                           xmlNodePtr prop, xmlNodePtr resp,
820                           struct propstat propstat[], void *rock);
821 int propfind_owner(const xmlChar *name, xmlNsPtr ns,
822                    struct propfind_ctx *fctx,
823                    xmlNodePtr prop, xmlNodePtr resp,
824                    struct propstat propstat[], void *rock);
825 int propfind_supprivset(const xmlChar *name, xmlNsPtr ns,
826                         struct propfind_ctx *fctx,
827                         xmlNodePtr prop, xmlNodePtr resp,
828                         struct propstat propstat[], void *rock);
829 int propfind_curprivset(const xmlChar *name, xmlNsPtr ns,
830                         struct propfind_ctx *fctx,
831                         xmlNodePtr prop, xmlNodePtr resp,
832                         struct propstat propstat[], void *rock);
833 int propfind_acl(const xmlChar *name, xmlNsPtr ns,
834                  struct propfind_ctx *fctx,
835                  xmlNodePtr prop, xmlNodePtr resp,
836                  struct propstat propstat[], void *rock);
837 int propfind_aclrestrict(const xmlChar *name, xmlNsPtr ns,
838                          struct propfind_ctx *fctx,
839                          xmlNodePtr prop, xmlNodePtr resp,
840                          struct propstat propstat[], void *rock);
841 int propfind_princolset(const xmlChar *name, xmlNsPtr ns,
842                         struct propfind_ctx *fctx,
843                         xmlNodePtr prop, xmlNodePtr resp,
844                         struct propstat propstat[], void *rock);
845 
846 int propfind_quota(const xmlChar *name, xmlNsPtr ns,
847                    struct propfind_ctx *fctx,
848                    xmlNodePtr prop, xmlNodePtr resp,
849                    struct propstat propstat[], void *rock);
850 
851 int propfind_curprin(const xmlChar *name, xmlNsPtr ns,
852                      struct propfind_ctx *fctx,
853                      xmlNodePtr prop, xmlNodePtr resp,
854                      struct propstat propstat[], void *rock);
855 
856 int propfind_serverinfo(const xmlChar *name, xmlNsPtr ns,
857                         struct propfind_ctx *fctx,
858                         xmlNodePtr prop, xmlNodePtr resp,
859                         struct propstat propstat[], void *rock);
860 
861 int propfind_addmember(const xmlChar *name, xmlNsPtr ns,
862                        struct propfind_ctx *fctx,
863                        xmlNodePtr prop, xmlNodePtr resp,
864                        struct propstat propstat[], void *rock);
865 
866 int propfind_sync_token(const xmlChar *name, xmlNsPtr ns,
867                         struct propfind_ctx *fctx,
868                         xmlNodePtr prop, xmlNodePtr resp,
869                         struct propstat propstat[], void *rock);
870 
871 int propfind_bulkrequests(const xmlChar *name, xmlNsPtr ns,
872                           struct propfind_ctx *fctx,
873                           xmlNodePtr prop, xmlNodePtr resp,
874                           struct propstat propstat[], void *rock);
875 
876 int propfind_calurl(const xmlChar *name, xmlNsPtr ns,
877                     struct propfind_ctx *fctx,
878                     xmlNodePtr prop, xmlNodePtr resp,
879                     struct propstat propstat[], void *rock);
880 int propfind_caluseraddr(const xmlChar *name, xmlNsPtr ns,
881                          struct propfind_ctx *fctx,
882                          xmlNodePtr prop, xmlNodePtr resp,
883                          struct propstat propstat[], void *rock);
884 int propfind_caluseremail(const xmlChar *name, xmlNsPtr ns,
885                          struct propfind_ctx *fctx,
886                          xmlNodePtr prop, xmlNodePtr resp,
887                          struct propstat propstat[], void *rock);
888 int proppatch_caluseraddr(xmlNodePtr prop, unsigned set,
889                           struct proppatch_ctx *pctx,
890                           struct propstat propstat[], void *rock);
891 int propfind_calusertype(const xmlChar *name, xmlNsPtr ns,
892                          struct propfind_ctx *fctx,
893                          xmlNodePtr prop, xmlNodePtr resp,
894                          struct propstat propstat[], void *rock);
895 int propfind_abookhome(const xmlChar *name, xmlNsPtr ns,
896                        struct propfind_ctx *fctx,
897                        xmlNodePtr prop, xmlNodePtr resp,
898                        struct propstat propstat[], void *rock);
899 
900 int propfind_push_transports(const xmlChar *name, xmlNsPtr ns,
901                              struct propfind_ctx *fctx,
902                              xmlNodePtr prop, xmlNodePtr resp,
903                              struct propstat propstat[], void *rock);
904 int propfind_pushkey(const xmlChar *name, xmlNsPtr ns,
905                      struct propfind_ctx *fctx,
906                      xmlNodePtr prop, xmlNodePtr resp,
907                      struct propstat propstat[], void *rock);
908 
909 /* PROPPATCH callbacks */
910 int proppatch_todb(xmlNodePtr prop, unsigned set, struct proppatch_ctx *pctx,
911                    struct propstat propstat[], void *rock);
912 int proppatch_restype(xmlNodePtr prop, unsigned set, struct proppatch_ctx *pctx,
913                       struct propstat propstat[], void *rock);
914 
915 #endif /* HTTP_DAV_H */
916