indent -kr -i8 -brf -bbb -fnc -l132 -nce on all of webcit-classic
[citadel.git] / webcit / dav_propfind.c
index ebf145291cce8104f6c6b9b4018d3e44a2632dbc..61e7e71c72bc756600694ac450449da923fddab7 100644 (file)
@@ -1,5 +1,6 @@
+
 /*
- * Handles GroupDAV PROPFIND requests.
+ * Handles GroupDAV and CalDAV PROPFIND requests.
  *
  * A few notes about our XML output:
  *
  *     This makes it difficult to read, but we have discovered clients which
  *     crash when you try to pretty it up.
  *
- * Copyright (c) 2005-2011 by the citadel.org team
+ * References:
+ * http://www.ietf.org/rfc/rfc4791.txt
+ * http://blogs.nologin.es/rickyepoderi/index.php?/archives/14-Introducing-CalDAV-Part-I.html
+ * https://msdn.microsoft.com/en-us/library/aa142960(v=exchg.65).aspx
+ *
+ * Copyright (c) 2005-2017 by the citadel.org team
  *
  * This program is open source software; you can redistribute it and/or
  * modify it under the terms of the GNU General Public License version 3.
  * but WITHOUT ANY WARRANTY; without even the implied warranty of
  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  * GNU General Public License for more details.
- *
  */
 
 #include "webcit.h"
 #include "webserver.h"
 #include "dav.h"
 
-extern int DisableGzip;
-
 /*
  * Given an encoded UID, translate that to an unencoded Citadel EUID and
  * then search for it in the current room.  Return a message number or -1
@@ -49,7 +52,7 @@ long locate_message_by_uid(const char *uid) {
                retval = atol(&buf[4]);
        }
 
-       return(retval);
+       return (retval);
 }
 
 
@@ -57,19 +60,18 @@ long locate_message_by_uid(const char *uid) {
  * IgnoreFloor: set to 0 or 1 _nothing else_
  * Subfolders: direct child floors will be put here.
  */
-const folder *GetRESTFolder(int IgnoreFloor, HashList *Subfolders)
-{
-       wcsession  *WCC = WC;
+const folder *GetRESTFolder(int IgnoreFloor, HashList * Subfolders) {
+       wcsession *WCC = WC;
        void *vFolder;
        const folder *ThisFolder = NULL;
        const folder *FoundFolder = NULL;
        const folder *BestGuess = NULL;
        int nBestGuess = 0;
-       HashPos    *itd, *itfl;
-       StrBuf     * Dir;
-       void       *vDir;
-       long        len;
-        const char *Key;
+       HashPos *itd, *itfl;
+       StrBuf *Dir;
+       void *vDir;
+       long len;
+       const char *Key;
        int iRoom, jURL, urlp;
        int delta;
 
@@ -81,87 +83,70 @@ const folder *GetRESTFolder(int IgnoreFloor, HashList *Subfolders)
        itfl = GetNewHashPos(WCC->Floors, 0);
        urlp = GetCount(WCC->Directory);
 
-       while (GetNextHashPos(WCC->Floors, itfl, &len, &Key, &vFolder) && 
-              (ThisFolder == NULL))
-       {
+       while (GetNextHashPos(WCC->Floors, itfl, &len, &Key, &vFolder) && (ThisFolder == NULL)) {
                ThisFolder = vFolder;
-               if (!IgnoreFloor && /* so we can handle legacy URLS... */
+               if (!IgnoreFloor &&     /* so we can handle legacy URLS... */
                    (ThisFolder->Floor != WCC->CurrentFloor))
                        continue;
 
-               if (ThisFolder->nRoomNameParts > 1) 
-               {
+               if (ThisFolder->nRoomNameParts > 1) {
                        /*TODO: is that number all right? */
-//                     if (urlp - ThisFolder->nRoomNameParts != 2) {
-//                             if (BestGuess != NULL)
-//                                     continue;
+//                      if (urlp - ThisFolder->nRoomNameParts != 2) {
+//                              if (BestGuess != NULL)
+//                                      continue;
 //ThisFolder->name
-//                             itd  = GetNewHashPos(WCC->Directory, 0);
-//                             GetNextHashPos(WCC->Directory, itd, &len, &Key, &vDir); //TODO: how many to fast forward?
-//                     }
-                       itd  = GetNewHashPos(WCC->Directory, 0);
-                       GetNextHashPos(WCC->Directory, itd, &len, &Key, &vDir); //TODO: how many to fast forward?
-       
-                       for (iRoom = 0, /* Fast forward the floorname as we checked it above: */ jURL = IgnoreFloor; 
-
-                            (iRoom <= ThisFolder->nRoomNameParts) && (jURL <= urlp); 
-
-                            iRoom++, jURL++, GetNextHashPos(WCC->Directory, itd, &len, &Key, &vDir))
-                       {
-                               Dir = (StrBuf*)vDir;
-                               if (strcmp(ChrPtr(ThisFolder->RoomNameParts[iRoom]), 
-                                          ChrPtr(Dir)) != 0)
-                               {
+//                              itd  = GetNewHashPos(WCC->Directory, 0);
+//                              GetNextHashPos(WCC->Directory, itd, &len, &Key, &vDir); //TODO: how many to fast forward?
+//                      }
+                       itd = GetNewHashPos(WCC->Directory, 0);
+                       GetNextHashPos(WCC->Directory, itd, &len, &Key, &vDir); //TODO: how many to fast forward?
+
+                       for (iRoom = 0, /* Fast forward the floorname as we checked it above: */ jURL = IgnoreFloor;
+                            (iRoom <= ThisFolder->nRoomNameParts) && (jURL <= urlp);
+                            iRoom++, jURL++, GetNextHashPos(WCC->Directory, itd, &len, &Key, &vDir)) {
+                               Dir = (StrBuf *) vDir;
+                               if (strcmp(ChrPtr(ThisFolder->RoomNameParts[iRoom]), ChrPtr(Dir)) != 0) {
                                        DeleteHashPos(&itd);
                                        continue;
                                }
                        }
                        DeleteHashPos(&itd);
                        /* Gotcha? */
-                       if ((iRoom == ThisFolder->nRoomNameParts) && (jURL == urlp))
-                       {
+                       if ((iRoom == ThisFolder->nRoomNameParts) && (jURL == urlp)) {
                                FoundFolder = ThisFolder;
                        }
-                       /* URL got more parts then this room, so we remember it for the best guess*/
-                       else if ((jURL <= urlp) &&
-                                (ThisFolder->nRoomNameParts <= nBestGuess))
-                       {
+                       /* URL got more parts then this room, so we remember it for the best guess */
+                       else if ((jURL <= urlp) && (ThisFolder->nRoomNameParts <= nBestGuess)) {
                                BestGuess = ThisFolder;
                                nBestGuess = jURL - 1;
                        }
                        /* Room has more parts than the URL, it might be a sub-room? */
-                       else if (iRoom <ThisFolder->nRoomNameParts) 
-                       {//// TODO: ThisFolder->nRoomNameParts == urlp - IgnoreFloor???
-                               Put(Subfolders, SKEY(ThisFolder->name), 
+                       else if (iRoom < ThisFolder->nRoomNameParts) {  //// TODO: ThisFolder->nRoomNameParts == urlp - IgnoreFloor???
+                               Put(Subfolders, SKEY(ThisFolder->name),
                                    /* Cast away const, its a reference. */
-                                   (void*)ThisFolder, reference_free_handler);
+                                   (void *) ThisFolder, reference_free_handler);
                        }
                }
                else {
                        delta = GetCount(WCC->Directory) - ThisFolder->nRoomNameParts;
                        if ((delta != 2) && (nBestGuess > 1))
-                           continue;
-                       
-                       itd  = GetNewHashPos(WCC->Directory, 0);
-                                               
-                       if (!GetNextHashPos(WCC->Directory, 
-                                           itd, &len, &Key, &vDir) ||
-                           (vDir == NULL))
-                       {
+                               continue;
+
+                       itd = GetNewHashPos(WCC->Directory, 0);
+
+                       if (!GetNextHashPos(WCC->Directory, itd, &len, &Key, &vDir) || (vDir == NULL)) {
                                DeleteHashPos(&itd);
-                               
-                               syslog(0, "5\n");
+
+                               syslog(LOG_DEBUG, "5\n");
                                continue;
                        }
                        DeleteHashPos(&itd);
-                       Dir = (StrBuf*) vDir;
-                       if (strcmp(ChrPtr(ThisFolder->name), 
-                                              ChrPtr(Dir))
-                           != 0)
-                       {
+                       Dir = (StrBuf *) vDir;
+                       if (strcmp(ChrPtr(ThisFolder->name), ChrPtr(Dir))
+                           != 0) {
                                DeleteHashPos(&itd);
-                               
-                               syslog(0, "5\n");
+
+                               syslog(LOG_DEBUG, "5\n");
                                continue;
                        }
                        DeleteHashPos(&itfl);
@@ -170,7 +155,7 @@ const folder *GetRESTFolder(int IgnoreFloor, HashList *Subfolders)
                                nBestGuess = 1;
                                BestGuess = ThisFolder;
                        }
-                       else 
+                       else
                                FoundFolder = ThisFolder;
                }
        }
@@ -186,9 +171,8 @@ const folder *GetRESTFolder(int IgnoreFloor, HashList *Subfolders)
 
 
 
-long GotoRestRoom(HashList *SubRooms)
-{
-       int IgnoreFloor = 0; /* deprecated... */
+long GotoRestRoom(HashList * SubRooms) {
+       int IgnoreFloor = 0;    /* deprecated... */
        wcsession *WCC = WC;
        long Count;
        long State;
@@ -196,44 +180,42 @@ long GotoRestRoom(HashList *SubRooms)
 
        State = REST_TOPLEVEL;
 
-       if (WCC->Hdr->HR.Handler != NULL) 
+       if (WCC->Hdr->HR.Handler != NULL)
                State |= REST_IN_NAMESPACE;
 
        Count = GetCount(WCC->Directory);
-       
-       if (Count == 0) return State;
 
-       if (Count >= 1) State |=REST_IN_FLOOR;
-       if (Count == 1) return State;
-       
+       if (Count == 0)
+               return State;
+
+       if (Count >= 1)
+               State |= REST_IN_FLOOR;
+       if (Count == 1)
+               return State;
+
        /* 
         * More than 3 params and no floor found? 
         * -> fall back to old non-floored notation
         */
        if ((Count >= 3) && (WCC->CurrentFloor == NULL))
                IgnoreFloor = 1;
-       if (Count >= 3)
-       {
+       if (Count >= 3) {
                IgnoreFloor = 0;
                State |= REST_IN_FLOOR;
 
                ThisFolder = GetRESTFolder(IgnoreFloor, SubRooms);
-               if (ThisFolder != NULL)
-               {
+               if (ThisFolder != NULL) {
                        if (WCC->ThisRoom != NULL)
                                if (CompareRooms(WCC->ThisRoom, ThisFolder) != 0)
                                        gotoroom(ThisFolder->name);
                        State |= REST_IN_ROOM;
-                       
+
                }
                if (GetCount(SubRooms) > 0)
                        State |= REST_HAVE_SUB_ROOMS;
        }
-       if ((WCC->ThisRoom != NULL) && 
-           (Count + IgnoreFloor > 3))
-       {
-               if (WCC->Hdr->HR.Handler->RID(ExistsID, IgnoreFloor))
-               {
+       if ((WCC->ThisRoom != NULL) && (Count + IgnoreFloor > 3)) {
+               if (WCC->Hdr->HR.Handler->RID(ExistsID, IgnoreFloor)) {
                        State |= REST_GOT_LOCAL_PART;
                }
                else {
@@ -252,8 +234,7 @@ long GotoRestRoom(HashList *SubRooms)
  * List rooms (or "collections" in DAV terminology) which contain
  * interesting groupware objects.
  */
-void dav_collection_list(void)
-{
+void dav_collection_list(void) {
        wcsession *WCC = WC;
        char buf[256];
        char roomname[256];
@@ -262,6 +243,7 @@ void dav_collection_list(void)
        time_t now;
        time_t mtime;
        int is_groupware_collection = 0;
+
        int starting_point = 1;         /**< 0 for /, 1 for /groupdav/ */
 
        if (WCC->Hdr->HR.Handler == NULL) {
@@ -285,34 +267,32 @@ void dav_collection_list(void)
        dav_common_headers();
        hprintf("Date: %s\r\n", datestring);
        hprintf("Content-type: text/xml\r\n");
-       if (DisableGzip || (!WCC->Hdr->HR.gzip_ok))     
+       if (DisableGzip || (!WCC->Hdr->HR.gzip_ok))
                hprintf("Content-encoding: identity\r\n");
 
        begin_burst();
 
-       wc_printf("<?xml version=\"1.0\" encoding=\"utf-8\"?>"
-               "<multistatus xmlns=\"DAV:\" xmlns:G=\"http://groupdav.org/\">"
-       );
+       wc_printf("<?xml version=\"1.0\" encoding=\"utf-8\"?>" "<multistatus xmlns=\"DAV:\" xmlns:G=\"http://groupdav.org/\">");
 
        /*
         * If the client is requesting the root, show a root node.
         */
        if (starting_point == 0) {
                wc_printf("<response>");
-                       wc_printf("<href>");
-                               dav_identify_host();
-                               wc_printf("/");
-                       wc_printf("</href>");
-                       wc_printf("<propstat>");
-                               wc_printf("<status>HTTP/1.1 200 OK</status>");
-                               wc_printf("<prop>");
-                                       wc_printf("<displayname>/</displayname>");
-                                       wc_printf("<resourcetype><collection/></resourcetype>");
-                                       wc_printf("<getlastmodified>");
-                                               escputs(datestring);
-                                       wc_printf("</getlastmodified>");
-                               wc_printf("</prop>");
-                       wc_printf("</propstat>");
+               wc_printf("<href>");
+               dav_identify_host();
+               wc_printf("/");
+               wc_printf("</href>");
+               wc_printf("<propstat>");
+               wc_printf("<status>HTTP/1.1 200 OK</status>");
+               wc_printf("<prop>");
+               wc_printf("<displayname>/</displayname>");
+               wc_printf("<resourcetype><collection/></resourcetype>");
+               wc_printf("<getlastmodified>");
+               escputs(datestring);
+               wc_printf("</getlastmodified>");
+               wc_printf("</prop>");
+               wc_printf("</propstat>");
                wc_printf("</response>");
        }
 
@@ -321,20 +301,20 @@ void dav_collection_list(void)
         */
        if ((starting_point + WCC->Hdr->HR.dav_depth) >= 1) {
                wc_printf("<response>");
-                       wc_printf("<href>");
-                               dav_identify_host();
-                               wc_printf("/groupdav");
-                       wc_printf("</href>");
-                       wc_printf("<propstat>");
-                               wc_printf("<status>HTTP/1.1 200 OK</status>");
-                               wc_printf("<prop>");
-                                       wc_printf("<displayname>GroupDAV</displayname>");
-                                       wc_printf("<resourcetype><collection/></resourcetype>");
-                                       wc_printf("<getlastmodified>");
-                                               escputs(datestring);
-                                       wc_printf("</getlastmodified>");
-                               wc_printf("</prop>");
-                       wc_printf("</propstat>");
+               wc_printf("<href>");
+               dav_identify_host();
+               wc_printf("/groupdav");
+               wc_printf("</href>");
+               wc_printf("<propstat>");
+               wc_printf("<status>HTTP/1.1 200 OK</status>");
+               wc_printf("<prop>");
+               wc_printf("<displayname>GroupDAV</displayname>");
+               wc_printf("<resourcetype><collection/></resourcetype>");
+               wc_printf("<getlastmodified>");
+               escputs(datestring);
+               wc_printf("</getlastmodified>");
+               wc_printf("</prop>");
+               wc_printf("</propstat>");
                wc_printf("</response>");
        }
 
@@ -343,84 +323,82 @@ void dav_collection_list(void)
         */
        serv_puts("LKRA");
        serv_getln(buf, sizeof buf);
-       if (buf[0] == '1') while (serv_getln(buf, sizeof buf), strcmp(buf, "000")) {
-
-               extract_token(roomname, buf, 0, '|', sizeof roomname);
-               view = extract_int(buf, 7);
-               mtime = extract_long(buf, 8);
-               http_datestring(datestring, sizeof datestring, mtime);
-
-               /*
-                * For now, only list rooms that we know a GroupDAV client
-                * might be interested in.  In the future we may add
-                * the rest.
-                *
-                * We determine the type of objects which are stored in each
-                * room by looking at the *default* view for the room.  This
-                * allows, for example, a Calendar room to appear as a
-                * GroupDAV calendar even if the user has switched it to a
-                * Calendar List view.
-                */
-               if (    (view == VIEW_CALENDAR) || 
-                       (view == VIEW_TASKS) || 
-                       (view == VIEW_ADDRESSBOOK) ||
-                       (view == VIEW_NOTES) ||
-                       (view == VIEW_JOURNAL) ||
-                       (view == VIEW_WIKI)
-               ) {
-                       is_groupware_collection = 1;
-               }
-               else {
-                       is_groupware_collection = 0;
-               }
-
-               if ( (is_groupware_collection) && ((starting_point + WCC->Hdr->HR.dav_depth) >= 2) ) {
-                       wc_printf("<response>");
-
-                       wc_printf("<href>");
-                       dav_identify_host();
-                       wc_printf("/groupdav/");
-                       urlescputs(roomname);
-                       wc_printf("/</href>");
-
-                       wc_printf("<propstat>");
-                       wc_printf("<status>HTTP/1.1 200 OK</status>");
-                       wc_printf("<prop>");
-                       wc_printf("<displayname>");
-                       escputs(roomname);
-                       wc_printf("</displayname>");
-                       wc_printf("<resourcetype><collection/>");
-
-                       switch(view) {
-                       case VIEW_CALENDAR:
-                               wc_printf("<G:vevent-collection />");
-                               break;
-                       case VIEW_TASKS:
-                               wc_printf("<G:vtodo-collection />");
-                               break;
-                       case VIEW_ADDRESSBOOK:
-                               wc_printf("<G:vcard-collection />");
-                               break;
-                       case VIEW_NOTES:
-                               wc_printf("<G:vnotes-collection />");
-                               break;
-                       case VIEW_JOURNAL:
-                               wc_printf("<G:vjournal-collection />");
-                               break;
-                       case VIEW_WIKI:
-                               wc_printf("<G:wiki-collection />");
-                               break;
+       if (buf[0] == '1')
+               while (serv_getln(buf, sizeof buf), strcmp(buf, "000")) {
+
+                       extract_token(roomname, buf, 0, '|', sizeof roomname);
+                       view = extract_int(buf, 7);
+                       mtime = extract_long(buf, 8);
+                       http_datestring(datestring, sizeof datestring, mtime);
+
+                       /*
+                        * For now, only list rooms that we know a GroupDAV client
+                        * might be interested in.  In the future we may add
+                        * the rest.
+                        *
+                        * We determine the type of objects which are stored in each
+                        * room by looking at the *default* view for the room.  This
+                        * allows, for example, a Calendar room to appear as a
+                        * GroupDAV calendar even if the user has switched it to a
+                        * Calendar List view.
+                        */
+                       if ((view == VIEW_CALENDAR) ||
+                           (view == VIEW_TASKS) ||
+                           (view == VIEW_ADDRESSBOOK) || (view == VIEW_NOTES) || (view == VIEW_JOURNAL) || (view == VIEW_WIKI)
+                           ) {
+                               is_groupware_collection = 1;
+                       }
+                       else {
+                               is_groupware_collection = 0;
                        }
 
-                       wc_printf("</resourcetype>");
-                       wc_printf("<getlastmodified>");
+                       if ((is_groupware_collection) && ((starting_point + WCC->Hdr->HR.dav_depth) >= 2)) {
+                               wc_printf("<response>");
+
+                               wc_printf("<href>");
+                               dav_identify_host();
+                               wc_printf("/groupdav/");
+                               urlescputs(roomname);
+                               wc_printf("/</href>");
+
+                               wc_printf("<propstat>");
+                               wc_printf("<status>HTTP/1.1 200 OK</status>");
+                               wc_printf("<prop>");
+                               wc_printf("<displayname>");
+                               escputs(roomname);
+                               wc_printf("</displayname>");
+                               wc_printf("<resourcetype><collection/>");
+
+                               switch (view) {
+                               case VIEW_CALENDAR:
+                                       wc_printf("<G:vevent-collection />");
+                                       break;
+                               case VIEW_TASKS:
+                                       wc_printf("<G:vtodo-collection />");
+                                       break;
+                               case VIEW_ADDRESSBOOK:
+                                       wc_printf("<G:vcard-collection />");
+                                       break;
+                               case VIEW_NOTES:
+                                       wc_printf("<G:vnotes-collection />");
+                                       break;
+                               case VIEW_JOURNAL:
+                                       wc_printf("<G:vjournal-collection />");
+                                       break;
+                               case VIEW_WIKI:
+                                       wc_printf("<G:wiki-collection />");
+                                       break;
+                               }
+
+                               wc_printf("</resourcetype>");
+                               wc_printf("<getlastmodified>");
                                escputs(datestring);
-                       wc_printf("</getlastmodified>");
-                       wc_printf("</prop>");
-                       wc_printf("</propstat>");
-                       wc_printf("</response>");
+                               wc_printf("</getlastmodified>");
+                               wc_printf("</prop>");
+                               wc_printf("</propstat>");
+                               wc_printf("</response>");
+                       }
                }
-       }
        wc_printf("</multistatus>\n");
 
        end_burst();
@@ -428,11 +406,11 @@ void dav_collection_list(void)
 
 
 void propfind_xml_start(void *data, const char *supplied_el, const char **attr) {
-       syslog(LOG_DEBUG, "<%s>", supplied_el);
+       // syslog(LOG_DEBUG, "<%s>", supplied_el);
 }
 
 void propfind_xml_end(void *data, const char *supplied_el) {
-       syslog(LOG_DEBUG, "</%s>", supplied_el);
+       // syslog(LOG_DEBUG, "</%s>", supplied_el);
 }
 
 
@@ -440,8 +418,7 @@ void propfind_xml_end(void *data, const char *supplied_el) {
 /*
  * The pathname is always going to be /groupdav/room_name/msg_num
  */
-void dav_propfind(void) 
-{
+void dav_propfind(void) {
        wcsession *WCC = WC;
        StrBuf *dav_roomname;
        StrBuf *dav_uid;
@@ -468,10 +445,10 @@ void dav_propfind(void)
 
                const char *req = ChrPtr(WCC->upload);
                if (req) {
-                       req = strchr(req, '<');                 /* hunt for the first tag */
+                       req = strchr(req, '<'); /* hunt for the first tag */
                }
                if (!req) {
-                       req = "ERROR";                          /* force it to barf */
+                       req = "ERROR";  /* force it to barf */
                }
 
                i = XML_Parse(xp, req, strlen(req), 1);
@@ -490,7 +467,7 @@ void dav_propfind(void)
                dav_common_headers();
                hprintf("Date: %s\r\n", datestring);
                hprintf("Content-Type: text/plain\r\n");
-               wc_printf("An internal error has occurred at %s:%d.\r\n", __FILE__ , __LINE__ );
+               wc_printf("An internal error has occurred at %s:%d.\r\n", __FILE__, __LINE__);
                end_burst();
                return;
        }
@@ -500,6 +477,8 @@ void dav_propfind(void)
        StrBufExtract_token(dav_roomname, WCC->Hdr->HR.ReqLine, 0, '/');
        StrBufExtract_token(dav_uid, WCC->Hdr->HR.ReqLine, 1, '/');
 
+       syslog(LOG_DEBUG, "PROPFIND requested for '%s' at depth %d", ChrPtr(dav_roomname), WCC->Hdr->HR.dav_depth);
+
        /*
         * If the room name is blank, the client is requesting a folder list.
         */
@@ -537,17 +516,15 @@ void dav_propfind(void)
                        hprintf("HTTP/1.1 404 not found\r\n");
                        dav_common_headers();
                        hprintf("Content-Type: text/plain\r\n");
-                       wc_printf("Object \"%s\" was not found in the \"%s\" folder.\r\n",
-                               ChrPtr(dav_uid),
-                               ChrPtr(dav_roomname)
-                       );
+                       wc_printf("Object \"%s\" was not found in the \"%s\" folder.\r\n", ChrPtr(dav_uid), ChrPtr(dav_roomname)
+                           );
                        end_burst();
                        FreeStrBuf(&dav_roomname);
                        FreeStrBuf(&dav_uid);
                        return;
                }
 
-               /* Be rude.  Completely ignore the XML request and simply send them
+               /* Be rude.  Completely ignore the XML request and simply send them
                 * everything we know about (which is going to simply be the ETag and
                 * nothing else).  Let the client-side parser sort it out.
                 */
@@ -555,17 +532,15 @@ void dav_propfind(void)
                dav_common_headers();
                hprintf("Date: %s\r\n", datestring);
                hprintf("Content-type: text/xml\r\n");
-               if (DisableGzip || (!WCC->Hdr->HR.gzip_ok))     
+               if (DisableGzip || (!WCC->Hdr->HR.gzip_ok))
                        hprintf("Content-encoding: identity\r\n");
-       
+
                begin_burst();
-       
-               wc_printf("<?xml version=\"1.0\" encoding=\"utf-8\"?>"
-                       "<multistatus xmlns=\"DAV:\">"
-               );
+
+               wc_printf("<?xml version=\"1.0\" encoding=\"utf-8\"?>" "<multistatus xmlns=\"DAV:\">");
 
                wc_printf("<response>");
-               
+
                wc_printf("<href>");
                dav_identify_host();
                wc_printf("/groupdav/");
@@ -595,13 +570,16 @@ void dav_propfind(void)
 
 
        /*
-        * We got to this point, which means that the client is requesting
-        * a 'collection' (i.e. a list of all items in the room).
+        * If we get to this point the client is performing a PROPFIND on the room itself.
+        *
+        * We call it a room; DAV calls it a "collection."  We have to give it some properties
+        * of the room itself and then offer a list of all items contained therein.
         *
         * Be rude.  Completely ignore the XML request and simply send them
         * everything we know about (which is going to simply be the ETag and
         * nothing else).  Let the client-side parser sort it out.
         */
+       //syslog(LOG_DEBUG, "BE RUDE AND IGNORE: \033[31m%s\033[0m", ChrPtr(WC->upload) );
        hprintf("HTTP/1.0 207 Multi-Status\r\n");
        dav_common_headers();
        hprintf("Date: %s\r\n", datestring);
@@ -612,128 +590,123 @@ void dav_propfind(void)
        begin_burst();
 
        wc_printf("<?xml version=\"1.0\" encoding=\"utf-8\"?>"
-               "<multistatus "
-                       "xmlns=\"DAV:\" "
-                       "xmlns:G=\"http://groupdav.org/\" "
-                       "xmlns:CALDAV=\"urn:ietf:params:xml:ns:caldav\""
-               ">"
-       );
+                 "<D:multistatus "
+                 "xmlns:D=\"DAV:\" " "xmlns:G=\"http://groupdav.org/\" " "xmlns:C=\"urn:ietf:params:xml:ns:caldav\"" ">");
 
-       /* Transmit the collection resource (FIXME check depth and starting point) */
-       wc_printf("<response>");
+       /* Transmit the collection resource */
+       wc_printf("<D:response>");
 
-       wc_printf("<href>");
+       wc_printf("<D:href>");
        dav_identify_host();
        wc_printf("/groupdav/");
        urlescputs(ChrPtr(WCC->CurRoom.name));
-       wc_printf("</href>");
+       wc_printf("</D:href>");
 
-       wc_printf("<propstat>");
-       wc_printf("<status>HTTP/1.1 200 OK</status>");
-       wc_printf("<prop>");
-       wc_printf("<displayname>");
+       wc_printf("<D:propstat>");
+       wc_printf("<D:status>HTTP/1.1 200 OK</D:status>");
+       wc_printf("<D:prop>");
+       wc_printf("<D:displayname>");
        escputs(ChrPtr(WCC->CurRoom.name));
-       wc_printf("</displayname>");
-
-       wc_printf("<owner/>");          /* empty owner ought to be legal; see rfc3744 section 5.1 */
-
-       wc_printf("<resourcetype><collection/>");
-       switch(WCC->CurRoom.defview) {
-               case VIEW_CALENDAR:
-                       wc_printf("<G:vevent-collection />");
-                       wc_printf("<CALDAV:calendar />");
-                       break;
-               case VIEW_TASKS:
-                       wc_printf("<G:vtodo-collection />");
-                       break;
-               case VIEW_ADDRESSBOOK:
-                       wc_printf("<G:vcard-collection />");
-                       break;
+       wc_printf("</D:displayname>");
+
+       wc_printf("<D:owner/>");        /* empty owner ought to be legal; see rfc3744 section 5.1 */
+
+       wc_printf("<D:resourcetype><D:collection/>");
+       switch (WCC->CurRoom.defview) {
+       case VIEW_CALENDAR:
+               wc_printf("<G:vevent-collection />");
+               wc_printf("<C:calendar />");
+               break;
+       case VIEW_TASKS:
+               wc_printf("<G:vtodo-collection />");
+               break;
+       case VIEW_ADDRESSBOOK:
+               wc_printf("<G:vcard-collection />");
+               break;
        }
-       wc_printf("</resourcetype>");
+       wc_printf("</D:resourcetype>");
 
        /* FIXME get the mtime
-       wc_printf("<getlastmodified>");
-               escputs(datestring);
-       wc_printf("</getlastmodified>");
-       */
-       wc_printf("</prop>");
-       wc_printf("</propstat>");
-       wc_printf("</response>");
-
-       /* Transmit the collection listing (FIXME check depth and starting point) */
-
-       MsgNum = NewStrBuf();
-       serv_puts("MSGS ALL");
-
-       StrBuf_ServGetln(MsgNum);
-       if (GetServerStatus(MsgNum, NULL) == 1)
-               while (BufLen = StrBuf_ServGetln(MsgNum), 
-                      ((BufLen >= 0) && 
-                       ((BufLen != 3) || strcmp(ChrPtr(MsgNum), "000"))  ))
-               {
-                       msgs = realloc(msgs, ++num_msgs * sizeof(long));
-                       msgs[num_msgs-1] = StrTol(MsgNum);
-               }
+          wc_printf("<D:getlastmodified>");
+          escputs(datestring);
+          wc_printf("</D:getlastmodified>");
+        */
+       wc_printf("</D:prop>");
+       wc_printf("</D:propstat>");
+       wc_printf("</D:response>");
 
-       if (num_msgs > 0) for (i=0; i<num_msgs; ++i) {
+       /* If a depth greater than zero was specified, transmit the collection listing */
+
+       if (WCC->Hdr->HR.dav_depth > 0) {
+               MsgNum = NewStrBuf();
+               serv_puts("MSGS ALL");
 
-               syslog(LOG_DEBUG, "PROPFIND enumerating message # %ld", msgs[i]);
-               strcpy(uid, "");
-               now = (-1);
-               serv_printf("MSG0 %ld|3", msgs[i]);
                StrBuf_ServGetln(MsgNum);
                if (GetServerStatus(MsgNum, NULL) == 1)
-                       while (BufLen = StrBuf_ServGetln(MsgNum), 
-                              ((BufLen >= 0) && 
-                               ((BufLen != 3) || strcmp(ChrPtr(MsgNum), "000")) ))
-                       {
-                               if (!strncasecmp(ChrPtr(MsgNum), "exti=", 5)) {
-                                       strcpy(uid, &ChrPtr(MsgNum)[5]);
-                               }
-                               else if (!strncasecmp(ChrPtr(MsgNum), "time=", 5)) {
-                                       now = atol(&ChrPtr(MsgNum)[5]);
+                       while (BufLen = StrBuf_ServGetln(MsgNum),
+                              ((BufLen >= 0) && ((BufLen != 3) || strcmp(ChrPtr(MsgNum), "000")))) {
+                               msgs = realloc(msgs, ++num_msgs * sizeof(long));
+                               msgs[num_msgs - 1] = StrTol(MsgNum);
                        }
-               }
 
-               if (!IsEmptyStr(uid)) {
-                       wc_printf("<response>");
-                               wc_printf("<href>");
+               if (num_msgs > 0)
+                       for (i = 0; i < num_msgs; ++i) {
+
+                               syslog(LOG_DEBUG, "PROPFIND enumerating message # %ld", msgs[i]);
+                               strcpy(uid, "");
+                               now = (-1);
+                               serv_printf("MSG0 %ld|3", msgs[i]);
+                               StrBuf_ServGetln(MsgNum);
+                               if (GetServerStatus(MsgNum, NULL) == 1)
+                                       while (BufLen = StrBuf_ServGetln(MsgNum),
+                                              ((BufLen >= 0) && ((BufLen != 3) || strcmp(ChrPtr(MsgNum), "000")))) {
+                                               if (!strncasecmp(ChrPtr(MsgNum), "exti=", 5)) {
+                                                       strcpy(uid, &ChrPtr(MsgNum)[5]);
+                                               }
+                                               else if (!strncasecmp(ChrPtr(MsgNum), "time=", 5)) {
+                                                       now = atol(&ChrPtr(MsgNum)[5]);
+                                               }
+                                       }
+
+                               if (!IsEmptyStr(uid)) {
+                                       wc_printf("<D:response>");
+                                       wc_printf("<D:href>");
                                        dav_identify_host();
                                        wc_printf("/groupdav/");
                                        urlescputs(ChrPtr(WCC->CurRoom.name));
                                        euid_escapize(encoded_uid, uid);
                                        wc_printf("/%s", encoded_uid);
-                               wc_printf("</href>");
-                               switch(WCC->CurRoom.defview) {
-                               case VIEW_CALENDAR:
-                                       wc_printf("<getcontenttype>text/x-ical</getcontenttype>");
-                                       break;
-                               case VIEW_TASKS:
-                                       wc_printf("<getcontenttype>text/x-ical</getcontenttype>");
-                                       break;
-                               case VIEW_ADDRESSBOOK:
-                                       wc_printf("<getcontenttype>text/x-vcard</getcontenttype>");
-                                       break;
-                               }
-                               wc_printf("<propstat>");
-                                       wc_printf("<status>HTTP/1.1 200 OK</status>");
-                                       wc_printf("<prop>");
-                                               wc_printf("<getetag>\"%ld\"</getetag>", msgs[i]);
+                                       wc_printf("</D:href>");
+                                       wc_printf("<D:propstat>");
+                                       wc_printf("<D:status>HTTP/1.1 200 OK</D:status>");
+                                       wc_printf("<D:prop>");
+                                       wc_printf("<D:getetag>\"%ld\"</D:getetag>", msgs[i]);
+                                       switch (WCC->CurRoom.defview) {
+                                       case VIEW_CALENDAR:
+                                               wc_printf("<D:getcontenttype>text/x-ical</D:getcontenttype>");
+                                               break;
+                                       case VIEW_TASKS:
+                                               wc_printf("<D:getcontenttype>text/x-ical</D:getcontenttype>");
+                                               break;
+                                       case VIEW_ADDRESSBOOK:
+                                               wc_printf("<D:getcontenttype>text/x-vcard</D:getcontenttype>");
+                                               break;
+                                       }
                                        if (now > 0L) {
                                                http_datestring(datestring, sizeof datestring, now);
-                                               wc_printf("<getlastmodified>");
+                                               wc_printf("<D:getlastmodified>");
                                                escputs(datestring);
-                                               wc_printf("</getlastmodified>");
+                                               wc_printf("</D:getlastmodified>");
                                        }
-                                       wc_printf("</prop>");
-                               wc_printf("</propstat>");
-                       wc_printf("</response>");
-               }
+                                       wc_printf("</D:prop>");
+                                       wc_printf("</D:propstat>");
+                                       wc_printf("</D:response>");
+                               }
+                       }
+               FreeStrBuf(&MsgNum);
        }
-       FreeStrBuf(&MsgNum);
 
-       wc_printf("</multistatus>\n");
+       wc_printf("</D:multistatus>\n");
        end_burst();
 
        if (msgs != NULL) {
@@ -743,45 +716,34 @@ void dav_propfind(void)
 
 
 
-int ParseMessageListHeaders_EUID(StrBuf *Line, 
-                                const char **pos, 
-                                message_summary *Msg, 
-                                StrBuf *ConversionBuffer)
-{
+int ParseMessageListHeaders_EUID(StrBuf * Line,
+                                const char **pos, message_summary * Msg, StrBuf * ConversionBuffer, void **ViewSpecific) {
        Msg->euid = NewStrBuf();
-       StrBufExtract_NextToken(Msg->euid,  Line, pos, '|');
+       StrBufExtract_NextToken(Msg->euid, Line, pos, '|');
        Msg->date = StrBufExtractNext_long(Line, pos, '|');
-       
+
        return StrLength(Msg->euid) > 0;
 }
 
-int DavUIDL_GetParamsGetServerCall(SharedMessageStatus *Stat, 
-                                   void **ViewSpecific, 
-                                   long oper, 
-                                   char *cmd, 
-                                   long len)
-{
+int DavUIDL_GetParamsGetServerCall(SharedMessageStatus * Stat,
+                                  void **ViewSpecific, long oper, char *cmd, long len, char *filter, long flen) {
        Stat->defaultsortorder = 0;
        Stat->sortit = 0;
        Stat->load_seen = 0;
-       Stat->maxmsgs  = 9999999;
+       Stat->maxmsgs = 9999999;
 
        snprintf(cmd, len, "MSGS ALL|||2");
        return 200;
 }
 
-int DavUIDL_RenderView_or_Tail(SharedMessageStatus *Stat, 
-                               void **ViewSpecific, 
-                               long oper)
-{
-       
-       DoTemplate(HKEY("msg_listview"),NULL,&NoCtx);
-       
+int DavUIDL_RenderView_or_Tail(SharedMessageStatus * Stat, void **ViewSpecific, long oper) {
+
+       DoTemplate(HKEY("msg_listview"), NULL, &NoCtx);
+
        return 0;
 }
 
-int DavUIDL_Cleanup(void **ViewSpecific)
-{
+int DavUIDL_Cleanup(void **ViewSpecific) {
        /* Note: wDumpContent() will output one additional </div> tag. */
        /* We ought to move this out into template */
        wDumpContent(1);
@@ -792,17 +754,10 @@ int DavUIDL_Cleanup(void **ViewSpecific)
 
 
 
-void 
-InitModule_PROPFIND
-(void)
-{
-       RegisterReadLoopHandlerset(
-               eReadEUIDS,
-               DavUIDL_GetParamsGetServerCall,
-               NULL, /// TODO: is this right?
-               ParseMessageListHeaders_EUID,
-               NULL, //// ""
-               DavUIDL_RenderView_or_Tail,
-               DavUIDL_Cleanup);
+void InitModule_PROPFIND(void) {
+       RegisterReadLoopHandlerset(eReadEUIDS,
+                                  DavUIDL_GetParamsGetServerCall,
+                                  NULL,
+                                  NULL, ParseMessageListHeaders_EUID, NULL, DavUIDL_RenderView_or_Tail, DavUIDL_Cleanup, NULL);
 
 }