when generating subjects for calendar items do quoted printeable encoding
[citadel.git] / citadel / modules / calendar / serv_calendar.c
index 9d859b5ee196ff8bfe29adeff0a9af6c7745ffd4..cf448a057dd4a6d8f428387b07072a4e7d7b39dd 100644 (file)
@@ -1,38 +1,36 @@
 /* 
- * $Id$ 
- *
  * This module implements iCalendar object processing and the Calendar>
  * room on a Citadel server.  It handles iCalendar objects using the
  * iTIP protocol.  See RFCs 2445 and 2446.
  *
+ *
+ * Copyright (c) 1987-2011 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 as published by
+ *  the Free Software Foundation; either version 3 of the License, or
+ *  (at your option) any later version.
+ *
+ *  This program is distributed in the hope that it will be useful,
+ *  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.
+ *
+ *  You should have received a copy of the GNU General Public License
+ *  along with this program; if not, write to the Free Software
+ *  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
  */
 
 #define PRODID "-//Citadel//NONSGML Citadel Calendar//EN"
 
-#include "sysdep.h"
-#include <stdlib.h>
-#include <unistd.h>
-#include <sys/types.h>
-#include <limits.h>
-#include <stdio.h>
-#include <string.h>
-#ifdef HAVE_STRINGS_H
-#include <strings.h>
-#endif
+#include "ctdl_module.h"
+
 #include <libical/ical.h>
-#include <libcitadel.h>
-#include "citadel.h"
-#include "server.h"
-#include "citserver.h"
-#include "support.h"
-#include "config.h"
-#include "user_ops.h"
-#include "room_ops.h"
+
 #include "msgbase.h"
 #include "internet_addressing.h"
 #include "serv_calendar.h"
 #include "euidindex.h"
-#include "ctdl_module.h"
 #include "ical_dezonify.h"
 
 
@@ -52,7 +50,7 @@ icalcomponent *icalcomponent_new_citadel_vcalendar(void) {
 
        encaps = icalcomponent_new_vcalendar();
        if (encaps == NULL) {
-               CtdlLogPrintf(CTDL_CRIT, "ERROR: could not allocate component!\n");
+               syslog(LOG_CRIT, "ERROR: could not allocate component!\n");
                return NULL;
        }
 
@@ -188,13 +186,13 @@ void ical_send_a_reply(icalcomponent *request, char *action) {
        strcpy(summary_string, "Calendar item");
 
        if (request == NULL) {
-               CtdlLogPrintf(CTDL_ERR, "ERROR: trying to reply to NULL event?\n");
+               syslog(LOG_ERR, "ERROR: trying to reply to NULL event?\n");
                return;
        }
 
        the_reply = icalcomponent_new_clone(request);
        if (the_reply == NULL) {
-               CtdlLogPrintf(CTDL_ERR, "ERROR: cannot clone request\n");
+               syslog(LOG_ERR, "ERROR: cannot clone request\n");
                return;
        }
 
@@ -596,13 +594,13 @@ int ical_update_my_calendar_with_reply(icalcomponent *cal) {
        /* Figure out just what event it is we're dealing with */
        strcpy(uid, "--==<< InVaLiD uId >>==--");
        ical_learn_uid_of_reply(uid, cal);
-       CtdlLogPrintf(CTDL_DEBUG, "UID of event being replied to is <%s>\n", uid);
+       syslog(LOG_DEBUG, "UID of event being replied to is <%s>\n", uid);
 
        strcpy(hold_rm, CC->room.QRname);       /* save current room */
 
-       if (getroom(&CC->room, USERCALENDARROOM) != 0) {
-               getroom(&CC->room, hold_rm);
-               CtdlLogPrintf(CTDL_CRIT, "cannot get user calendar room\n");
+       if (CtdlGetRoom(&CC->room, USERCALENDARROOM) != 0) {
+               CtdlGetRoom(&CC->room, hold_rm);
+               syslog(LOG_CRIT, "cannot get user calendar room\n");
                return(2);
        }
 
@@ -612,11 +610,11 @@ int ical_update_my_calendar_with_reply(icalcomponent *cal) {
         * Citadel always sets the message EUID to the iCalendar UID of
         * the event, this will work.
         */
-       msgnum_being_replaced = locate_message_by_euid(uid, &CC->room);
+       msgnum_being_replaced = CtdlLocateMessageByEuid(uid, &CC->room);
 
-       getroom(&CC->room, hold_rm);    /* return to saved room */
+       CtdlGetRoom(&CC->room, hold_rm);        /* return to saved room */
 
-       CtdlLogPrintf(CTDL_DEBUG, "msgnum_being_replaced == %ld\n", msgnum_being_replaced);
+       syslog(LOG_DEBUG, "msgnum_being_replaced == %ld\n", msgnum_being_replaced);
        if (msgnum_being_replaced == 0) {
                return(1);                      /* no calendar event found */
        }
@@ -643,7 +641,7 @@ int ical_update_my_calendar_with_reply(icalcomponent *cal) {
 
        original_event = oec.c;
        if (original_event == NULL) {
-               CtdlLogPrintf(CTDL_ERR, "ERROR: Original_component is NULL.\n");
+               syslog(LOG_ERR, "ERROR: Original_component is NULL.\n");
                return(2);
        }
 
@@ -655,7 +653,7 @@ int ical_update_my_calendar_with_reply(icalcomponent *cal) {
        icalcomponent_free(original_event);     /* Don't need this anymore. */
        if (serialized_event == NULL) return(2);
 
-       MailboxName(roomname, sizeof roomname, &CC->user, USERCALENDARROOM);
+       CtdlMailboxName(roomname, sizeof roomname, &CC->user, USERCALENDARROOM);
 
        message_text = malloc(strlen(serialized_event) + SIZ);
        if (message_text != NULL) {
@@ -808,51 +806,64 @@ int ical_ctdl_is_overlap(
                        struct icaltimetype t2start,
                        struct icaltimetype t2end
 ) {
-
        if (icaltime_is_null_time(t1start)) return(0);
        if (icaltime_is_null_time(t2start)) return(0);
 
-       /* First, check for all-day events */
-       if (t1start.is_date) {
-               if (!icaltime_compare_date_only(t1start, t2start)) {
-                       return(1);
-               }
-               if (!icaltime_is_null_time(t2end)) {
-                       if (!icaltime_compare_date_only(t1start, t2end)) {
-                               return(1);
-                       }
+       /* if either event lacks end time, assume end = start */
+       if (icaltime_is_null_time(t1end))
+               memcpy(&t1end, &t1start, sizeof(struct icaltimetype));
+       else {
+               if (t1end.is_date && icaltime_compare(t1start, t1end)) {
+                        /*
+                         * the end date is non-inclusive so adjust it by one
+                         * day because our test is inclusive, note that a day is
+                         * not too much because we are talking about all day
+                         * events
+                        * if start = end we assume that nevertheless the whole
+                        * day is meant
+                         */
+                       icaltime_adjust(&t1end, -1, 0, 0, 0);   
                }
        }
 
-       if (t2start.is_date) {
-               if (!icaltime_compare_date_only(t2start, t1start)) {
-                       return(1);
-               }
-               if (!icaltime_is_null_time(t1end)) {
-                       if (!icaltime_compare_date_only(t2start, t1end)) {
-                               return(1);
-                       }
+       if (icaltime_is_null_time(t2end))
+               memcpy(&t2end, &t2start, sizeof(struct icaltimetype));
+       else {
+               if (t2end.is_date && icaltime_compare(t2start, t2end)) {
+                       icaltime_adjust(&t2end, -1, 0, 0, 0);   
                }
        }
 
-       /* Now check for overlaps using date *and* time. */
+       /* First, check for all-day events */
+       if (t1start.is_date || t2start.is_date) {
+               /* If event 1 ends before event 2 starts, we're in the clear. */
+               if (icaltime_compare_date_only(t1end, t2start) < 0) return(0);
 
-       /* First, bail out if either event 1 or event 2 is missing end time. */
-       if (icaltime_is_null_time(t1end)) return(0);
-       if (icaltime_is_null_time(t2end)) return(0);
+               /* If event 2 ends before event 1 starts, we're also ok. */
+               if (icaltime_compare_date_only(t2end, t1start) < 0) return(0);
+
+               return(1);
+       }
+
+       /* syslog(LOG_DEBUG, "Comparing t1start %d:%d t1end %d:%d t2start %d:%d t2end %d:%d \n",
+               t1start.hour, t1start.minute, t1end.hour, t1end.minute,
+               t2start.hour, t2start.minute, t2end.hour, t2end.minute);
+       */
+
+       /* Now check for overlaps using date *and* time. */
 
        /* If event 1 ends before event 2 starts, we're in the clear. */
        if (icaltime_compare(t1end, t2start) <= 0) return(0);
+       /* syslog(LOG_DEBUG, "first passed\n"); */
 
        /* If event 2 ends before event 1 starts, we're also ok. */
        if (icaltime_compare(t2end, t1start) <= 0) return(0);
+       /* syslog(LOG_DEBUG, "second passed\n"); */
 
        /* Otherwise, they overlap. */
        return(1);
 }
 
-
-
 /* 
  * Phase 6 of "hunt for conflicts"
  * called by ical_conflicts_phase5()
@@ -876,13 +887,13 @@ int ical_conflicts_phase6(struct icaltimetype t1start,
        /* debugging cruft *
        time_t tt;
        tt = icaltime_as_timet_with_zone(t1start, t1start.zone);
-       CtdlLogPrintf(CTDL_DEBUG, "PROPOSED START: %s", ctime(&tt));
+       syslog(LOG_DEBUG, "PROPOSED START: %s", ctime(&tt));
        tt = icaltime_as_timet_with_zone(t1end, t1end.zone);
-       CtdlLogPrintf(CTDL_DEBUG, "  PROPOSED END: %s", ctime(&tt));
+       syslog(LOG_DEBUG, "  PROPOSED END: %s", ctime(&tt));
        tt = icaltime_as_timet_with_zone(t2start, t2start.zone);
-       CtdlLogPrintf(CTDL_DEBUG, "EXISTING START: %s", ctime(&tt));
+       syslog(LOG_DEBUG, "EXISTING START: %s", ctime(&tt));
        tt = icaltime_as_timet_with_zone(t2end, t2end.zone);
-       CtdlLogPrintf(CTDL_DEBUG, "  EXISTING END: %s", ctime(&tt));
+       syslog(LOG_DEBUG, "  EXISTING END: %s", ctime(&tt));
        * debugging cruft */
 
        /* compare and output */
@@ -1159,8 +1170,8 @@ void ical_hunt_for_conflicts(icalcomponent *cal) {
 
        strcpy(hold_rm, CC->room.QRname);       /* save current room */
 
-       if (getroom(&CC->room, USERCALENDARROOM) != 0) {
-               getroom(&CC->room, hold_rm);
+       if (CtdlGetRoom(&CC->room, USERCALENDARROOM) != 0) {
+               CtdlGetRoom(&CC->room, hold_rm);
                cprintf("%d You do not have a calendar.\n", ERROR + ROOM_NOT_FOUND);
                return;
        }
@@ -1175,7 +1186,7 @@ void ical_hunt_for_conflicts(icalcomponent *cal) {
        );
 
        cprintf("000\n");
-       getroom(&CC->room, hold_rm);    /* return to saved room */
+       CtdlGetRoom(&CC->room, hold_rm);        /* return to saved room */
 
 }
 
@@ -1263,8 +1274,23 @@ void ical_add_to_freebusy(icalcomponent *fb, icalcomponent *top_level_cal) {
        /*
         * Now begin calculating the event start and end times.
         */
-       dtstart = icalcomponent_get_dtstart(cal);
-       if (icaltime_is_null_time(dtstart)) return;
+       p = icalcomponent_get_first_property(cal, ICAL_DTSTART_PROPERTY);
+       if (!p) return;
+       dtstart = icalproperty_get_dtstart(p);
+
+       if (icaltime_is_utc(dtstart)) {
+               dtstart.zone = icaltimezone_get_utc_timezone();
+       }
+       else {
+               dtstart.zone = icalcomponent_get_timezone(top_level_cal,
+                       icalparameter_get_tzid(
+                               icalproperty_get_first_parameter(p, ICAL_TZID_PARAMETER)
+                       )
+               );
+               if (!dtstart.zone) {
+                       dtstart.zone = get_default_icaltimezone();
+               }
+       }
 
        dtend = icalcomponent_get_dtend(cal);
        if (!icaltime_is_null_time(dtend)) {
@@ -1279,18 +1305,24 @@ void ical_add_to_freebusy(icalcomponent *fb, icalcomponent *top_level_cal) {
        }
 
        do {
-
-
-               // FIXME add timezone conversion, we are currently outputting floating times
-
-
-
                /* Convert the DTSTART and DTEND properties to an icalperiod. */
                this_event_period.start = dtstart;
        
                if (!icaltime_is_null_time(dtend)) {
                        this_event_period.end = dtend;
                }
+
+               /* Convert the timestamps to UTC.  It's ok to do this because we've already expanded
+                * recurrences and this data is never going to get used again.
+                */
+               this_event_period.start = icaltime_convert_to_zone(
+                       this_event_period.start,
+                       icaltimezone_get_utc_timezone()
+               );
+               this_event_period.end = icaltime_convert_to_zone(
+                       this_event_period.end,
+                       icaltimezone_get_utc_timezone()
+               );
        
                /* Now add it. */
                icalcomponent_add_property(fb, icalproperty_new_freebusy(this_event_period));
@@ -1300,11 +1332,11 @@ void ical_add_to_freebusy(icalcomponent *fb, icalcomponent *top_level_cal) {
                 */
                p = icalcomponent_get_first_property(fb, ICAL_DTSTART_PROPERTY);
                if (p == NULL) {
-                       icalcomponent_set_dtstart(fb, dtstart);
+                       icalcomponent_set_dtstart(fb, this_event_period.start);
                }
                else {
-                       if (icaltime_compare(dtstart, icalcomponent_get_dtstart(fb)) < 0) {
-                               icalcomponent_set_dtstart(fb, dtstart);
+                       if (icaltime_compare(this_event_period.start, icalcomponent_get_dtstart(fb)) < 0) {
+                               icalcomponent_set_dtstart(fb, this_event_period.start);
                        }
                }
        
@@ -1313,11 +1345,11 @@ void ical_add_to_freebusy(icalcomponent *fb, icalcomponent *top_level_cal) {
                 */
                p = icalcomponent_get_first_property(fb, ICAL_DTEND_PROPERTY);
                if (p == NULL) {
-                       icalcomponent_set_dtend(fb, dtend);
+                       icalcomponent_set_dtend(fb, this_event_period.end);
                }
                else {
-                       if (icaltime_compare(dtend, icalcomponent_get_dtend(fb)) > 0) {
-                               icalcomponent_set_dtend(fb, dtend);
+                       if (icaltime_compare(this_event_period.end, icalcomponent_get_dtend(fb)) > 0) {
+                               icalcomponent_set_dtend(fb, this_event_period.end);
                        }
                }
 
@@ -1325,6 +1357,8 @@ void ical_add_to_freebusy(icalcomponent *fb, icalcomponent *top_level_cal) {
                        dtstart = icalrecur_iterator_next(ritr);
                        if (!icaltime_is_null_time(dtend)) {
                                dtend = icaltime_add(dtstart, dur);
+                               dtend.zone = dtstart.zone;
+                               dtend.is_utc = dtstart.is_utc;
                        }
                        ++num_recur;
                }
@@ -1390,16 +1424,16 @@ void ical_freebusy(char *who) {
        int config_lines = 0;
 
        /* First try an exact match. */
-       found_user = getuser(&usbuf, who);
+       found_user = CtdlGetUser(&usbuf, who);
 
        /* If not found, try it as an unqualified email address. */
        if (found_user != 0) {
                strcpy(buf, who);
                recp = validate_recipients(buf, NULL, 0);
-               CtdlLogPrintf(CTDL_DEBUG, "Trying <%s>\n", buf);
+               syslog(LOG_DEBUG, "Trying <%s>\n", buf);
                if (recp != NULL) {
                        if (recp->num_local == 1) {
-                               found_user = getuser(&usbuf, recp->recp_local);
+                               found_user = CtdlGetUser(&usbuf, recp->recp_local);
                        }
                        free_recipients(recp);
                }
@@ -1410,11 +1444,11 @@ void ical_freebusy(char *who) {
         */
        if (found_user != 0) {
                snprintf(buf, sizeof buf, "%s@%s", who, config.c_fqdn);
-               CtdlLogPrintf(CTDL_DEBUG, "Trying <%s>\n", buf);
+               syslog(LOG_DEBUG, "Trying <%s>\n", buf);
                recp = validate_recipients(buf, NULL, 0);
                if (recp != NULL) {
                        if (recp->num_local == 1) {
-                               found_user = getuser(&usbuf, recp->recp_local);
+                               found_user = CtdlGetUser(&usbuf, recp->recp_local);
                        }
                        free_recipients(recp);
                }
@@ -1433,11 +1467,11 @@ void ical_freebusy(char *who) {
                        if ( (!strcasecmp(type, "localhost"))
                           || (!strcasecmp(type, "directory")) ) {
                                snprintf(buf, sizeof buf, "%s@%s", who, host);
-                               CtdlLogPrintf(CTDL_DEBUG, "Trying <%s>\n", buf);
+                               syslog(LOG_DEBUG, "Trying <%s>\n", buf);
                                recp = validate_recipients(buf, NULL, 0);
                                if (recp != NULL) {
                                        if (recp->num_local == 1) {
-                                               found_user = getuser(&usbuf, recp->recp_local);
+                                               found_user = CtdlGetUser(&usbuf, recp->recp_local);
                                        }
                                        free_recipients(recp);
                                }
@@ -1450,24 +1484,24 @@ void ical_freebusy(char *who) {
                return;
        }
 
-       MailboxName(calendar_room_name, sizeof calendar_room_name,
+       CtdlMailboxName(calendar_room_name, sizeof calendar_room_name,
                &usbuf, USERCALENDARROOM);
 
        strcpy(hold_rm, CC->room.QRname);       /* save current room */
 
-       if (getroom(&CC->room, calendar_room_name) != 0) {
+       if (CtdlGetRoom(&CC->room, calendar_room_name) != 0) {
                cprintf("%d Cannot open calendar\n", ERROR + ROOM_NOT_FOUND);
-               getroom(&CC->room, hold_rm);
+               CtdlGetRoom(&CC->room, hold_rm);
                return;
        }
 
        /* Create a VFREEBUSY subcomponent */
-       CtdlLogPrintf(CTDL_DEBUG, "Creating VFREEBUSY component\n");
+       syslog(LOG_DEBUG, "Creating VFREEBUSY component\n");
        fb = icalcomponent_new_vfreebusy();
        if (fb == NULL) {
                cprintf("%d Internal error: cannot allocate memory.\n",
                        ERROR + INTERNAL_ERROR);
-               getroom(&CC->room, hold_rm);
+               CtdlGetRoom(&CC->room, hold_rm);
                return;
        }
 
@@ -1489,7 +1523,7 @@ void ical_freebusy(char *who) {
        icalcomponent_add_property(fb, icalproperty_new_organizer(buf));
 
        /* Add busy time from events */
-       CtdlLogPrintf(CTDL_DEBUG, "Adding busy time from events\n");
+       syslog(LOG_DEBUG, "Adding busy time from events\n");
        CtdlForEachMessage(MSGS_ALL, 0, NULL, NULL, NULL, ical_freebusy_backend, (void *)fb );
 
        /* If values for DTSTART and DTEND are still not present, set them
@@ -1503,22 +1537,22 @@ void ical_freebusy(char *who) {
        }
 
        /* Put the freebusy component into the calendar component */
-       CtdlLogPrintf(CTDL_DEBUG, "Encapsulating\n");
+       syslog(LOG_DEBUG, "Encapsulating\n");
        encaps = ical_encapsulate_subcomponent(fb);
        if (encaps == NULL) {
                icalcomponent_free(fb);
                cprintf("%d Internal error: cannot allocate memory.\n",
                        ERROR + INTERNAL_ERROR);
-               getroom(&CC->room, hold_rm);
+               CtdlGetRoom(&CC->room, hold_rm);
                return;
        }
 
        /* Set the method to PUBLISH */
-       CtdlLogPrintf(CTDL_DEBUG, "Setting method\n");
+       syslog(LOG_DEBUG, "Setting method\n");
        icalcomponent_set_method(encaps, ICAL_METHOD_PUBLISH);
 
        /* Serialize it */
-       CtdlLogPrintf(CTDL_DEBUG, "Serializing\n");
+       syslog(LOG_DEBUG, "Serializing\n");
        serialized_request = icalcomponent_as_ical_string_r(encaps);
        icalcomponent_free(encaps);     /* Don't need this anymore. */
 
@@ -1530,7 +1564,7 @@ void ical_freebusy(char *who) {
        cprintf("\n000\n");
 
        /* Go back to the room from which we came... */
-       getroom(&CC->room, hold_rm);
+       CtdlGetRoom(&CC->room, hold_rm);
 }
 
 
@@ -1627,7 +1661,7 @@ void ical_getics(void)
 
        encaps = icalcomponent_new_vcalendar();
        if (encaps == NULL) {
-               CtdlLogPrintf(CTDL_DEBUG, "ERROR: could not allocate component!\n");
+               syslog(LOG_ALERT, "ERROR: could not allocate component!\n");
                cprintf("%d Could not allocate memory\n", ERROR+INTERNAL_ERROR);
                return;
        }
@@ -1670,7 +1704,7 @@ void ical_putics_grabtzids(icalparameter *param, void *data)
        HashList *keys = (HashList *) data;
        
        if ( (keys) && (tzid) && (!IsEmptyStr(tzid)) ) {
-               Put(keys, tzid, strlen(tzid), strdup(tzid), generic_free_handler);
+               Put(keys, tzid, strlen(tzid), strdup(tzid), NULL);
        }
 }
 
@@ -1705,7 +1739,7 @@ void ical_putics(void)
        }
 
        cprintf("%d Transmit data now\n", SEND_LISTING);
-       calstream = CtdlReadMessageBody("000", config.c_maxmsglen, NULL, 0, 0);
+       calstream = CtdlReadMessageBody(HKEY("000"), config.c_maxmsglen, NULL, 0, 0);
        if (calstream == NULL) {
                return;
        }
@@ -1753,7 +1787,7 @@ void ical_putics(void)
                                HashPos = GetNewHashPos(tzidlist, 0);
 
                                while (GetNextHashPos(tzidlist, HashPos, &len, &Key, &Value)) {
-                                       CtdlLogPrintf(CTDL_DEBUG, "Attaching timezone '%s'\n", Value);
+                                       syslog(LOG_DEBUG, "Attaching timezone '%s'\n", (char*) Value);
                                        icaltimezone *t = NULL;
 
                                        /* First look for a timezone attached to the original calendar */
@@ -1868,22 +1902,22 @@ void cmd_ical(char *argbuf)
 /*
  * We don't know if the calendar room exists so we just create it at login
  */
-void ical_create_room(void)
+void ical_CtdlCreateRoom(void)
 {
        struct ctdlroom qr;
-       struct visit vbuf;
+       visit vbuf;
 
        /* Create the calendar room if it doesn't already exist */
-       create_room(USERCALENDARROOM, 4, "", 0, 1, 0, VIEW_CALENDAR);
+       CtdlCreateRoom(USERCALENDARROOM, 4, "", 0, 1, 0, VIEW_CALENDAR);
 
        /* Set expiration policy to manual; otherwise objects will be lost! */
-       if (lgetroom(&qr, USERCALENDARROOM)) {
-               CtdlLogPrintf(CTDL_CRIT, "Couldn't get the user calendar room!\n");
+       if (CtdlGetRoomLock(&qr, USERCALENDARROOM)) {
+               syslog(LOG_CRIT, "Couldn't get the user calendar room!\n");
                return;
        }
        qr.QRep.expire_mode = EXPIRE_MANUAL;
        qr.QRdefaultview = VIEW_CALENDAR;       /* 3 = calendar view */
-       lputroom(&qr);
+       CtdlPutRoomLock(&qr);
 
        /* Set the view to a calendar view */
        CtdlGetRelationship(&vbuf, &CC->user, &qr);
@@ -1891,16 +1925,16 @@ void ical_create_room(void)
        CtdlSetRelationship(&vbuf, &CC->user, &qr);
 
        /* Create the tasks list room if it doesn't already exist */
-       create_room(USERTASKSROOM, 4, "", 0, 1, 0, VIEW_TASKS);
+       CtdlCreateRoom(USERTASKSROOM, 4, "", 0, 1, 0, VIEW_TASKS);
 
        /* Set expiration policy to manual; otherwise objects will be lost! */
-       if (lgetroom(&qr, USERTASKSROOM)) {
-               CtdlLogPrintf(CTDL_CRIT, "Couldn't get the user calendar room!\n");
+       if (CtdlGetRoomLock(&qr, USERTASKSROOM)) {
+               syslog(LOG_CRIT, "Couldn't get the user calendar room!\n");
                return;
        }
        qr.QRep.expire_mode = EXPIRE_MANUAL;
        qr.QRdefaultview = VIEW_TASKS;
-       lputroom(&qr);
+       CtdlPutRoomLock(&qr);
 
        /* Set the view to a task list view */
        CtdlGetRelationship(&vbuf, &CC->user, &qr);
@@ -1908,16 +1942,16 @@ void ical_create_room(void)
        CtdlSetRelationship(&vbuf, &CC->user, &qr);
 
        /* Create the notes room if it doesn't already exist */
-       create_room(USERNOTESROOM, 4, "", 0, 1, 0, VIEW_NOTES);
+       CtdlCreateRoom(USERNOTESROOM, 4, "", 0, 1, 0, VIEW_NOTES);
 
        /* Set expiration policy to manual; otherwise objects will be lost! */
-       if (lgetroom(&qr, USERNOTESROOM)) {
-               CtdlLogPrintf(CTDL_CRIT, "Couldn't get the user calendar room!\n");
+       if (CtdlGetRoomLock(&qr, USERNOTESROOM)) {
+               syslog(LOG_CRIT, "Couldn't get the user calendar room!\n");
                return;
        }
        qr.QRep.expire_mode = EXPIRE_MANUAL;
        qr.QRdefaultview = VIEW_NOTES;
-       lputroom(&qr);
+       CtdlPutRoomLock(&qr);
 
        /* Set the view to a notes view */
        CtdlGetRelationship(&vbuf, &CC->user, &qr);
@@ -1952,14 +1986,16 @@ void ical_send_out_invitations(icalcomponent *top_level_cal, icalcomponent *cal)
        size_t reqsize;
        icalproperty *p;
        struct icaltimetype t;
-       icaltimezone *attached_zones[5] = { NULL, NULL, NULL, NULL, NULL };
+       const icaltimezone *attached_zones[5] = { NULL, NULL, NULL, NULL, NULL };
        int i;
-       icaltimezone *z;
+       const icaltimezone *z;
        int num_zones_attached = 0;
        int zone_already_attached;
+       icalparameter *tzidp = NULL;
+       const char *tzidc = NULL;
 
        if (cal == NULL) {
-               CtdlLogPrintf(CTDL_ERR, "ERROR: trying to reply to NULL event?\n");
+               syslog(LOG_ERR, "ERROR: trying to reply to NULL event?\n");
                return;
        }
 
@@ -1977,7 +2013,7 @@ void ical_send_out_invitations(icalcomponent *top_level_cal, icalcomponent *cal)
        /* Clone the event */
        the_request = icalcomponent_new_clone(cal);
        if (the_request == NULL) {
-               CtdlLogPrintf(CTDL_ERR, "ERROR: cannot clone calendar object\n");
+               syslog(LOG_ERR, "ERROR: cannot clone calendar object\n");
                return;
        }
 
@@ -2013,7 +2049,7 @@ void ical_send_out_invitations(icalcomponent *top_level_cal, icalcomponent *cal)
                }
        }
 
-       CtdlLogPrintf(CTDL_DEBUG, "<%d> attendees: <%s>\n", num_attendees, attendees_string);
+       syslog(LOG_DEBUG, "<%d> attendees: <%s>\n", num_attendees, attendees_string);
 
        /* If there are no attendees, there are no invitations to send, so...
         * don't bother putting one together!  Punch out, Maverick!
@@ -2026,7 +2062,7 @@ void ical_send_out_invitations(icalcomponent *top_level_cal, icalcomponent *cal)
        /* Encapsulate the VEVENT component into a complete VCALENDAR */
        encaps = icalcomponent_new_vcalendar();
        if (encaps == NULL) {
-               CtdlLogPrintf(CTDL_DEBUG, "ERROR: could not allocate component!\n");
+               syslog(LOG_ALERT, "ERROR: could not allocate component!\n");
                icalcomponent_free(the_request);
                return;
        }
@@ -2060,9 +2096,15 @@ void ical_send_out_invitations(icalcomponent *top_level_cal, icalcomponent *cal)
                  || (icalproperty_isa(p) == ICAL_RECURRENCEID_PROPERTY)
                ) {
                        t = icalproperty_get_dtstart(p);        // it's safe to use dtstart for all of them
-                       CtdlLogPrintf(CTDL_DEBUG, "Found an icaltimetype: %s\n",
-                               icaltime_as_ical_string(t)
-                       );
+
+                       /* Determine the tzid in order for some of the conditions below to work */
+                       tzidp = icalproperty_get_first_parameter(p, ICAL_TZID_PARAMETER);
+                       if (tzidp) {
+                               tzidc = icalparameter_get_tzid(tzidp);
+                       }
+                       else {
+                               tzidc = NULL;
+                       }
 
                        /* First see if there's a timezone attached to the data structure itself */
                        if (icaltime_is_utc(t)) {
@@ -2071,40 +2113,29 @@ void ical_send_out_invitations(icalcomponent *top_level_cal, icalcomponent *cal)
                        else {
                                z = icaltime_get_timezone(t);
                        }
-                       if (z) CtdlLogPrintf(CTDL_DEBUG, "Timezone is present in data structure\n");
 
                        /* If not, try to determine the tzid from the parameter using attached zones */
-                       if (!z) {
-                               z = icalcomponent_get_timezone(top_level_cal,
-                                       icalparameter_get_tzid(
-                                               icalproperty_get_first_parameter(p, ICAL_TZID_PARAMETER)
-                                       )
-                               );
-                               if (z) CtdlLogPrintf(CTDL_DEBUG, "Timezone was found in attached zones\n");
+                       if ((!z) && (tzidc)) {
+                               z = icalcomponent_get_timezone(top_level_cal, tzidc);
                        }
 
                        /* Still no good?  Try our internal database */
-                       if (!z) {
-                               z = icaltimezone_get_builtin_timezone_from_tzid(
-                                       icalparameter_get_tzid(
-                                               icalproperty_get_first_parameter(p, ICAL_TZID_PARAMETER)
-                                       )
-                               );
-                               if (z) CtdlLogPrintf(CTDL_DEBUG, "Timezone was found in internal db\n");
+                       if ((!z) && (tzidc)) {
+                               z = icaltimezone_get_builtin_timezone_from_tzid(tzidc);
                        }
 
                        if (z) {
-                               CtdlLogPrintf(CTDL_DEBUG, "Have valid timezone, need to attach it.\n");
+                               /* We have a valid timezone.  Good.  Now we need to attach it. */
 
                                zone_already_attached = 0;
                                for (i=0; i<5; ++i) {
                                        if (z == attached_zones[i]) {
+                                               /* We've already got this one, no need to attach another. */
                                                ++zone_already_attached;
-                                               CtdlLogPrintf(CTDL_DEBUG, "zone already attached!!\n");
                                        }
                                }
                                if ((!zone_already_attached) && (num_zones_attached < 5)) {
-                                       CtdlLogPrintf(CTDL_DEBUG, "attach zone %d\n", num_zones_attached);
+                                       /* This is a new one, so attach it. */
                                        attached_zones[num_zones_attached++] = z;
                                }
 
@@ -2133,8 +2164,6 @@ void ical_send_out_invitations(icalcomponent *top_level_cal, icalcomponent *cal)
        icalcomponent_free(encaps);     /* Don't need this anymore. */
        if (serialized_request == NULL) return;
 
-       CtdlLogPrintf(CTDL_DEBUG, "SENDING INVITATIONS:\n%s\n", serialized_request);
-
        reqsize = strlen(serialized_request) + SIZ;
        request_message_text = malloc(reqsize);
        if (request_message_text != NULL) {
@@ -2143,16 +2172,20 @@ void ical_send_out_invitations(icalcomponent *top_level_cal, icalcomponent *cal)
                        serialized_request
                );
 
-               msg = CtdlMakeMessage(&CC->user,
-                       "",                     /* No single recipient here */
-                       "",                     /* No single recipient here */
-                       CC->room.QRname, 0, FMT_RFC822,
-                       "",
-                       "",
+               msg = CtdlMakeMessage(
+                       &CC->user,
+                       NULL,                   /* No single recipient here */
+                       NULL,                   /* No single recipient here */
+                       CC->room.QRname,
+                       0,
+                       FMT_RFC822,
+                       NULL,
+                       NULL,
                        summary_string,         /* Use summary for subject */
                        NULL,
                        request_message_text,
-                       NULL);
+                       NULL
+               );
        
                if (msg != NULL) {
                        valid = validate_recipients(attendees_string, NULL, 0);
@@ -2181,7 +2214,7 @@ void ical_saving_vevent(icalcomponent *top_level_cal, icalcomponent *cal) {
        icalproperty *organizer = NULL;
        char organizer_string[SIZ];
 
-       CtdlLogPrintf(CTDL_DEBUG, "ical_saving_vevent() has been called!\n");
+       syslog(LOG_DEBUG, "ical_saving_vevent() has been called!\n");
 
        /* Don't send out invitations unless the client wants us to. */
        if (CIT_ICAL->server_generated_invitations == 0) {
@@ -2296,7 +2329,7 @@ void ical_obj_beforesave_backend(char *name, char *filename, char *partnum,
                                                free(msg->cm_fields['E']);
                                        }
                                        msg->cm_fields['E'] = strdup(buf);
-                                       CtdlLogPrintf(CTDL_DEBUG, "Saving calendar UID <%s>\n", buf);
+                                       syslog(LOG_DEBUG, "Saving calendar UID <%s>\n", buf);
                                }
                        }
 
@@ -2309,7 +2342,7 @@ void ical_obj_beforesave_backend(char *name, char *filename, char *partnum,
                                        if (msg->cm_fields['U'] != NULL) {
                                                free(msg->cm_fields['U']);
                                        }
-                                       msg->cm_fields['U'] = strdup(buf);
+                                       msg->cm_fields['U'] = rfc2047encode(buf, strlen(buf));
                                }
                        }
 
@@ -2357,7 +2390,7 @@ int ical_obj_beforesave(struct CtdlMessage *msg)
 
        /* It must be an RFC822 message! */
        if (msg->cm_format_type != 4) {
-               CtdlLogPrintf(CTDL_DEBUG, "Rejecting non-RFC822 message\n");
+               syslog(LOG_DEBUG, "Rejecting non-RFC822 message\n");
                return(1);              /* You tried to save a non-RFC822 message! */
        }
 
@@ -2423,7 +2456,7 @@ int ical_obj_aftersave(struct CtdlMessage *msg)
         */
 
        /* First determine if this is our room */
-       MailboxName(roomname, sizeof roomname, &CC->user, USERCALENDARROOM);
+       CtdlMailboxName(roomname, sizeof roomname, &CC->user, USERCALENDARROOM);
        if (strcasecmp(roomname, CC->room.QRname)) {
                return(0);      /* Not the Calendar room -- don't do anything. */
        }
@@ -2554,7 +2587,7 @@ CTDL_MODULE_INIT(calendar)
                /* Initialize our hook functions */
                CtdlRegisterMessageHook(ical_obj_beforesave, EVT_BEFORESAVE);
                CtdlRegisterMessageHook(ical_obj_aftersave, EVT_AFTERSAVE);
-               CtdlRegisterSessionHook(ical_create_room, EVT_LOGIN);
+               CtdlRegisterSessionHook(ical_CtdlCreateRoom, EVT_LOGIN);
                CtdlRegisterProtoHook(cmd_ical, "ICAL", "Citadel iCal commands");
                CtdlRegisterSessionHook(ical_session_startup, EVT_START);
                CtdlRegisterSessionHook(ical_session_shutdown, EVT_STOP);
@@ -2564,5 +2597,5 @@ CTDL_MODULE_INIT(calendar)
        }
        
        /* return our Subversion id for the Log */
-       return "$Id$";
+       return "calendar";
 }