X-Git-Url: https://code.citadel.org/?p=citadel.git;a=blobdiff_plain;f=citadel%2Fmodules%2Fcalendar%2Fserv_calendar.c;h=c38ffd250b5c1103cff240adebe9f03be68f8929;hp=7e51606319fbe265b2a04d8ada354a2a4ab558db;hb=5ac2920028e92a453c686c799327d7a66b3e7b49;hpb=f808d5319551a6581b3b12a519fa725e0fc64325 diff --git a/citadel/modules/calendar/serv_calendar.c b/citadel/modules/calendar/serv_calendar.c index 7e5160631..c38ffd250 100644 --- a/citadel/modules/calendar/serv_calendar.c +++ b/citadel/modules/calendar/serv_calendar.c @@ -1,41 +1,30 @@ /* - * $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-2020 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. + * + * 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. */ #define PRODID "-//Citadel//NONSGML Citadel Calendar//EN" -#include "sysdep.h" -#include -#include -#include -#include -#include -#include -#ifdef HAVE_STRINGS_H -#include -#endif +#include "ctdl_module.h" #include -#include -#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 "room_ops.h" #include "euidindex.h" -#include "ctdl_module.h" -#include "ical_dezonify.h" - - +#include "default_timezone.h" +#include "config.h" struct ical_respond_data { char desired_partnum[SIZ]; @@ -52,7 +41,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_ERR, "calendar: could not allocate component"); return NULL; } @@ -91,8 +80,6 @@ icalcomponent *ical_encapsulate_subcomponent(icalcomponent *subcomp) { } - - /* * Write a calendar object into the specified user's calendar room. * If the supplied user is NULL, this function writes the calendar object @@ -100,6 +87,7 @@ icalcomponent *ical_encapsulate_subcomponent(icalcomponent *subcomp) { */ void ical_write_to_cal(struct ctdluser *u, icalcomponent *cal) { char *ser = NULL; + long serlen; icalcomponent *encaps = NULL; struct CtdlMessage *msg = NULL; icalcomponent *tmp=NULL; @@ -121,13 +109,15 @@ void ical_write_to_cal(struct ctdluser *u, icalcomponent *cal) { ser = icalcomponent_as_ical_string_r(cal); if (ser == NULL) return; + serlen = strlen(ser); + /* If the caller supplied a user, write to that user's default calendar room */ if (u) { /* This handy API function does all the work for us. */ CtdlWriteObject(USERCALENDARROOM, /* which room */ "text/calendar", /* MIME type */ ser, /* data */ - strlen(ser)+1, /* length */ + serlen + 1, /* length */ u, /* which user */ 0, /* not binary */ 0, /* don't delete others of this type */ @@ -137,22 +127,26 @@ void ical_write_to_cal(struct ctdluser *u, icalcomponent *cal) { /* If the caller did not supply a user, write to the currently selected room */ if (!u) { + struct CitContext *CCC = CC; + StrBuf *MsgBody; + msg = malloc(sizeof(struct CtdlMessage)); memset(msg, 0, sizeof(struct CtdlMessage)); msg->cm_magic = CTDLMESSAGE_MAGIC; msg->cm_anon_type = MES_NORMAL; msg->cm_format_type = 4; - msg->cm_fields['A'] = strdup(CC->user.fullname); - msg->cm_fields['O'] = strdup(CC->room.QRname); - msg->cm_fields['N'] = strdup(config.c_nodename); - msg->cm_fields['H'] = strdup(config.c_humannode); - msg->cm_fields['M'] = malloc(strlen(ser) + 40); - strcpy(msg->cm_fields['M'], "Content-type: text/calendar\r\n\r\n"); - strcat(msg->cm_fields['M'], ser); + CM_SetField(msg, eAuthor, CCC->user.fullname, strlen(CCC->user.fullname)); + CM_SetField(msg, eOriginalRoom, CCC->room.QRname, strlen(CCC->room.QRname)); + + MsgBody = NewStrBufPlain(NULL, serlen + 100); + StrBufAppendBufPlain(MsgBody, HKEY("Content-type: text/calendar\r\n\r\n"), 0); + StrBufAppendBufPlain(MsgBody, ser, serlen, 0); + + CM_SetAsFieldSB(msg, eMesageText, &MsgBody); /* Now write the data */ CtdlSubmitMsg(msg, NULL, "", QP_EADDR); - CtdlFreeMessage(msg); + CM_Free(msg); } /* In either case, now we can free the serialized calendar object */ @@ -177,24 +171,25 @@ void ical_send_a_reply(icalcomponent *request, char *action) { icalproperty *summary = NULL; char summary_string[SIZ]; icalproperty *me_attend = NULL; - struct recptypes *recp = NULL; + recptypes *recp = NULL; icalparameter *partstat = NULL; char *serialized_reply = NULL; char *reply_message_text = NULL; + const char *ch; struct CtdlMessage *msg = NULL; - struct recptypes *valid = NULL; + recptypes *valid = NULL; - strcpy(organizer_string, ""); + *organizer_string = '\0'; strcpy(summary_string, "Calendar item"); if (request == NULL) { - CtdlLogPrintf(CTDL_ERR, "ERROR: trying to reply to NULL event?\n"); + syslog(LOG_ERR, "calendar: trying to reply to NULL event"); return; } the_reply = icalcomponent_new_clone(request); if (the_reply == NULL) { - CtdlLogPrintf(CTDL_ERR, "ERROR: cannot clone request\n"); + syslog(LOG_ERR, "calendar: cannot clone request"); return; } @@ -210,22 +205,20 @@ void ical_send_a_reply(icalcomponent *request, char *action) { while (attendee = icalcomponent_get_first_property(vevent, ICAL_ATTENDEE_PROPERTY), (attendee != NULL) ) { - if (icalproperty_get_attendee(attendee)) { - strcpy(attendee_string, - icalproperty_get_attendee(attendee) ); - if (!strncasecmp(attendee_string, "MAILTO:", 7)) { - strcpy(attendee_string, &attendee_string[7]); - striplt(attendee_string); - recp = validate_recipients(attendee_string, NULL, 0); - if (recp != NULL) { - if (!strcasecmp(recp->recp_local, CC->user.fullname)) { - if (me_attend) icalproperty_free(me_attend); - me_attend = icalproperty_new_clone(attendee); - } - free_recipients(recp); + ch = icalproperty_get_attendee(attendee); + if ((ch != NULL) && !strncasecmp(ch, "MAILTO:", 7)) { + safestrncpy(attendee_string, ch + 7, sizeof (attendee_string)); + striplt(attendee_string); + recp = validate_recipients(attendee_string, NULL, 0); + if (recp != NULL) { + if (!strcasecmp(recp->recp_local, CC->user.fullname)) { + if (me_attend) icalproperty_free(me_attend); + me_attend = icalproperty_new_clone(attendee); } + free_recipients(recp); } } + /* Remove it... */ icalcomponent_remove_property(vevent, attendee); icalproperty_free(attendee); @@ -234,7 +227,7 @@ void ical_send_a_reply(icalcomponent *request, char *action) { /* We found our own address in the attendee list. */ if (me_attend) { /* Change the partstat from NEEDS-ACTION to ACCEPT or DECLINE */ - icalproperty_remove_parameter(me_attend, ICAL_PARTSTAT_PARAMETER); + icalproperty_remove_parameter_by_kind(me_attend, ICAL_PARTSTAT_PARAMETER); if (!strcasecmp(action, "accept")) { partstat = icalparameter_new_partstat(ICAL_PARTSTAT_ACCEPTED); @@ -305,7 +298,7 @@ void ical_send_a_reply(icalcomponent *request, char *action) { if (msg != NULL) { valid = validate_recipients(organizer_string, NULL, 0); CtdlSubmitMsg(msg, valid, "", QP_EADDR); - CtdlFreeMessage(msg); + CM_Free(msg); free_recipients(valid); } } @@ -313,7 +306,6 @@ void ical_send_a_reply(icalcomponent *request, char *action) { } - /* * Callback function for mime parser that hunts for calendar content types * and turns them into calendar objects. If something is found, it is placed @@ -368,7 +360,7 @@ void ical_respond(long msgnum, char *partnum, char *action) { return; } - msg = CtdlFetchMessage(msgnum, 1); + msg = CtdlFetchMessage(msgnum, 1, 1); if (msg == NULL) { cprintf("%d Message %ld not found.\n", ERROR + ILLEGAL_VALUE, @@ -379,18 +371,17 @@ void ical_respond(long msgnum, char *partnum, char *action) { memset(&ird, 0, sizeof ird); strcpy(ird.desired_partnum, partnum); - mime_parser(msg->cm_fields['M'], - NULL, - *ical_locate_part, /* callback function */ - NULL, NULL, - (void *) &ird, /* user data */ - 0 + mime_parser(CM_RANGE(msg, eMesageText), + *ical_locate_part, /* callback function */ + NULL, NULL, + (void *) &ird, /* user data */ + 0 ); /* We're done with the incoming message, because we now have a * calendar object in memory. */ - CtdlFreeMessage(msg); + CM_Free(msg); /* * Here is the real meat of this function. Handle the event. @@ -540,10 +531,13 @@ STARTOVER: /* Check to see if these two attendees match... */ - if (!strcasecmp( - icalproperty_get_attendee(e_attendee), - icalproperty_get_attendee(r_attendee) - )) { + const char *e, *r; + e = icalproperty_get_attendee(e_attendee); + r = icalproperty_get_attendee(r_attendee); + + if ((e != NULL) && + (r != NULL) && + !strcasecmp(e, r)) { /* ...and if they do, remove the attendee from the event * and replace it with the attendee from the reply. (The * reply's copy will have the same address, but an updated @@ -571,8 +565,6 @@ STARTOVER: } - - /* * Handle an incoming RSVP (object with method==ICAL_METHOD_REPLY) for a * calendar event. The object has already been deserialized for us; all @@ -596,13 +588,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, "calendar: UID of event being replied to is <%s>", 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_ERR, "calendar: cannot get user calendar room"); return(2); } @@ -612,11 +604,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, "calendar: msgnum_being_replaced == %ld", msgnum_being_replaced); if (msgnum_being_replaced == 0) { return(1); /* no calendar event found */ } @@ -627,23 +619,22 @@ int ical_update_my_calendar_with_reply(icalcomponent *cal) { * us the ability to load the event into memory so we can diddle the * attendees. */ - msg = CtdlFetchMessage(msgnum_being_replaced, 1); + msg = CtdlFetchMessage(msgnum_being_replaced, 1, 1); if (msg == NULL) { return(2); /* internal error */ } oec.c = NULL; - mime_parser(msg->cm_fields['M'], - NULL, - *ical_locate_original_event, /* callback function */ - NULL, NULL, - &oec, /* user data */ - 0 + mime_parser(CM_RANGE(msg, eMesageText), + *ical_locate_original_event, /* callback function */ + NULL, NULL, + &oec, /* user data */ + 0 ); - CtdlFreeMessage(msg); + CM_Free(msg); original_event = oec.c; if (original_event == NULL) { - CtdlLogPrintf(CTDL_ERR, "ERROR: Original_component is NULL.\n"); + syslog(LOG_ERR, "calendar: original_component is NULL"); return(2); } @@ -655,7 +646,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) { @@ -679,7 +670,7 @@ int ical_update_my_calendar_with_reply(icalcomponent *cal) { if (msg != NULL) { CIT_ICAL->avoid_sending_invitations = 1; CtdlSubmitMsg(msg, NULL, roomname, QP_EADDR); - CtdlFreeMessage(msg); + CM_Free(msg); CIT_ICAL->avoid_sending_invitations = 0; } } @@ -708,7 +699,7 @@ void ical_handle_rsvp(long msgnum, char *partnum, char *action) { return; } - msg = CtdlFetchMessage(msgnum, 1); + msg = CtdlFetchMessage(msgnum, 1, 1); if (msg == NULL) { cprintf("%d Message %ld not found.\n", ERROR + ILLEGAL_VALUE, @@ -719,18 +710,17 @@ void ical_handle_rsvp(long msgnum, char *partnum, char *action) { memset(&ird, 0, sizeof ird); strcpy(ird.desired_partnum, partnum); - mime_parser(msg->cm_fields['M'], - NULL, - *ical_locate_part, /* callback function */ - NULL, NULL, - (void *) &ird, /* user data */ - 0 - ); + mime_parser(CM_RANGE(msg, eMesageText), + *ical_locate_part, /* callback function */ + NULL, NULL, + (void *) &ird, /* user data */ + 0 + ); /* We're done with the incoming message, because we now have a * calendar object in memory. */ - CtdlFreeMessage(msg); + CM_Free(msg); /* * Here is the real meat of this function. Handle the event. @@ -847,7 +837,7 @@ int ical_ctdl_is_overlap( return(1); } - /* lprintf (9, "Comparing t1start %d:%d t1end %d:%d t2start %d:%d t2end %d:%d \n", + /* syslog(LOG_DEBUG, "Comparing t1start %d:%d t1end %d:%d t2start %d:%d t2end %d:%d", t1start.hour, t1start.minute, t1end.hour, t1end.minute, t2start.hour, t2start.minute, t2end.hour, t2end.minute); */ @@ -856,16 +846,17 @@ int ical_ctdl_is_overlap( /* If event 1 ends before event 2 starts, we're in the clear. */ if (icaltime_compare(t1end, t2start) <= 0) return(0); - /* lprintf(9, "first passed\n"); */ + /* syslog(LOG_DEBUG, "calendar: first passed"); */ /* If event 2 ends before event 1 starts, we're also ok. */ if (icaltime_compare(t2end, t1start) <= 0) return(0); - /* lprintf(9, "second passed\n"); */ + /* syslog(LOG_DEBUG, "calendar: second passed"); */ /* Otherwise, they overlap. */ return(1); } + /* * Phase 6 of "hunt for conflicts" * called by ical_conflicts_phase5() @@ -889,13 +880,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 */ @@ -905,11 +896,11 @@ int ical_conflicts_phase6(struct icaltimetype t1start, existing_msgnum, conflict_event_uid, conflict_event_summary, - ( ((strlen(compare_uid)>0) + ( (!IsEmptyStr(compare_uid) &&(!strcasecmp(compare_uid, conflict_event_uid))) ? 1 : 0 - ) - ); + ) + ); conflict_reported = 1; } @@ -917,7 +908,6 @@ int ical_conflicts_phase6(struct icaltimetype t1start, } - /* * Phase 5 of "hunt for conflicts" * Called by ical_conflicts_phase4() @@ -986,6 +976,9 @@ void ical_conflicts_phase5(struct icaltimetype t1start, } dur = icaltime_subtract(t2end, t2start); } + else { + memset (&dur, 0, sizeof(struct icaldurationtype)); + } rrule = ical_ctdl_get_subprop(existing_event, ICAL_RRULE_PROPERTY); if (rrule) { @@ -1029,8 +1022,6 @@ void ical_conflicts_phase5(struct icaltimetype t1start, } - - /* * Phase 4 of "hunt for conflicts" * Called by ical_hunt_for_conflicts_backend() @@ -1043,8 +1034,6 @@ void ical_conflicts_phase4(icalcomponent *proposed_event, long existing_msgnum) { struct icaltimetype t1start, t1end; - t1start = icaltime_null_time(); - t1end = icaltime_null_time(); icalproperty *p; char compare_uid[SIZ]; @@ -1056,13 +1045,17 @@ void ical_conflicts_phase4(icalcomponent *proposed_event, int num_recur = 0; /* initialization */ - strcpy(compare_uid, ""); + t1end = icaltime_null_time(); + *compare_uid = '\0'; /* proposed event stuff */ p = ical_ctdl_get_subprop(proposed_event, ICAL_DTSTART_PROPERTY); - if (p == NULL) return; - if (p != NULL) t1start = icalproperty_get_dtstart(p); + if (p == NULL) + return; + else + t1start = icalproperty_get_dtstart(p); + if (icaltime_is_utc(t1start)) { t1start.zone = icaltimezone_get_utc_timezone(); } @@ -1097,6 +1090,9 @@ void ical_conflicts_phase4(icalcomponent *proposed_event, dur = icaltime_subtract(t1end, t1start); } + else { + memset (&dur, 0, sizeof(struct icaldurationtype)); + } rrule = ical_ctdl_get_subprop(proposed_event, ICAL_RRULE_PROPERTY); if (rrule) { @@ -1127,7 +1123,6 @@ void ical_conflicts_phase4(icalcomponent *proposed_event, } - /* * Phase 3 of "hunt for conflicts" * Called by ical_hunt_for_conflicts() @@ -1139,18 +1134,17 @@ void ical_hunt_for_conflicts_backend(long msgnum, void *data) { proposed_event = (icalcomponent *)data; - msg = CtdlFetchMessage(msgnum, 1); + msg = CtdlFetchMessage(msgnum, 1, 1); if (msg == NULL) return; memset(&ird, 0, sizeof ird); strcpy(ird.desired_partnum, "_HUNT_"); - mime_parser(msg->cm_fields['M'], - NULL, - *ical_locate_part, /* callback function */ - NULL, NULL, - (void *) &ird, /* user data */ - 0 + mime_parser(CM_RANGE(msg, eMesageText), + *ical_locate_part, /* callback function */ + NULL, NULL, + (void *) &ird, /* user data */ + 0 ); - CtdlFreeMessage(msg); + CM_Free(msg); if (ird.cal == NULL) return; @@ -1159,7 +1153,6 @@ void ical_hunt_for_conflicts_backend(long msgnum, void *data) { } - /* * Phase 2 of "hunt for conflicts" operation. * At this point we have a calendar object which represents the VEVENT that @@ -1172,8 +1165,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; } @@ -1188,12 +1181,11 @@ 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 */ } - /* * Hunt for conflicts (Phase 1 -- retrieve the object and call Phase 2) */ @@ -1201,7 +1193,7 @@ void ical_conflicts(long msgnum, char *partnum) { struct CtdlMessage *msg = NULL; struct ical_respond_data ird; - msg = CtdlFetchMessage(msgnum, 1); + msg = CtdlFetchMessage(msgnum, 1, 1); if (msg == NULL) { cprintf("%d Message %ld not found\n", ERROR + ILLEGAL_VALUE, @@ -1212,15 +1204,14 @@ void ical_conflicts(long msgnum, char *partnum) { memset(&ird, 0, sizeof ird); strcpy(ird.desired_partnum, partnum); - mime_parser(msg->cm_fields['M'], - NULL, - *ical_locate_part, /* callback function */ - NULL, NULL, - (void *) &ird, /* user data */ - 0 - ); + mime_parser(CM_RANGE(msg, eMesageText), + *ical_locate_part, /* callback function */ + NULL, NULL, + (void *) &ird, /* user data */ + 0 + ); - CtdlFreeMessage(msg); + CM_Free(msg); if (ird.cal != NULL) { ical_hunt_for_conflicts(ird.cal); @@ -1232,7 +1223,6 @@ void ical_conflicts(long msgnum, char *partnum) { } - /* * Look for busy time in a VEVENT and add it to the supplied VFREEBUSY. * @@ -1244,8 +1234,8 @@ void ical_add_to_freebusy(icalcomponent *fb, icalcomponent *top_level_cal) { icalproperty *p; icalvalue *v; struct icalperiodtype this_event_period = icalperiodtype_null_period(); - icaltimetype dtstart = icaltime_null_time(); - icaltimetype dtend = icaltime_null_time(); + icaltimetype dtstart; + icaltimetype dtend; /* recur variables */ icalproperty *rrule = NULL; @@ -1298,6 +1288,9 @@ void ical_add_to_freebusy(icalcomponent *fb, icalcomponent *top_level_cal) { if (!icaltime_is_null_time(dtend)) { dur = icaltime_subtract(dtend, dtstart); } + else { + memset (&dur, 0, sizeof(struct icaldurationtype)); + } /* Is a recurrence specified? If so, get ready to process it... */ rrule = ical_ctdl_get_subprop(cal, ICAL_RRULE_PROPERTY); @@ -1360,7 +1353,6 @@ void ical_add_to_freebusy(icalcomponent *fb, icalcomponent *top_level_cal) { if (!icaltime_is_null_time(dtend)) { dtend = icaltime_add(dtstart, dur); dtend.zone = dtstart.zone; - dtend.is_utc = dtstart.is_utc; } ++num_recur; } @@ -1370,7 +1362,6 @@ void ical_add_to_freebusy(icalcomponent *fb, icalcomponent *top_level_cal) { } - /* * Backend for ical_freebusy() * @@ -1386,18 +1377,17 @@ void ical_freebusy_backend(long msgnum, void *data) { fb = (icalcomponent *)data; /* User-supplied data will be the VFREEBUSY component */ - msg = CtdlFetchMessage(msgnum, 1); + msg = CtdlFetchMessage(msgnum, 1, 1); if (msg == NULL) return; memset(&ird, 0, sizeof ird); strcpy(ird.desired_partnum, "_HUNT_"); - mime_parser(msg->cm_fields['M'], - NULL, - *ical_locate_part, /* callback function */ - NULL, NULL, - (void *) &ird, /* user data */ - 0 - ); - CtdlFreeMessage(msg); + mime_parser(CM_RANGE(msg, eMesageText), + *ical_locate_part, /* callback function */ + NULL, NULL, + (void *) &ird, /* user data */ + 0 + ); + CM_Free(msg); if (ird.cal) { ical_add_to_freebusy(fb, ird.cal); /* Add VEVENT times to VFREEBUSY */ @@ -1406,7 +1396,6 @@ void ical_freebusy_backend(long msgnum, void *data) { } - /* * Grab another user's free/busy times */ @@ -1418,7 +1407,7 @@ void ical_freebusy(char *who) { icalcomponent *encaps = NULL; icalcomponent *fb = NULL; int found_user = (-1); - struct recptypes *recp = NULL; + recptypes *recp = NULL; char buf[256]; char host[256]; char type[256]; @@ -1426,16 +1415,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, "calendar: trying <%s>", 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); } @@ -1445,12 +1434,12 @@ void ical_freebusy(char *who) { * primary FQDN of this Citadel node. */ if (found_user != 0) { - snprintf(buf, sizeof buf, "%s@%s", who, config.c_fqdn); - CtdlLogPrintf(CTDL_DEBUG, "Trying <%s>\n", buf); + snprintf(buf, sizeof buf, "%s@%s", who, CtdlGetConfigStr("c_fqdn")); + syslog(LOG_DEBUG, "calendar: trying <%s>", 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); } @@ -1469,11 +1458,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, "calendar: trying <%s>", 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); } @@ -1486,24 +1475,23 @@ 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, "calendar: creating VFREEBUSY component"); fb = icalcomponent_new_vfreebusy(); if (fb == NULL) { - cprintf("%d Internal error: cannot allocate memory.\n", - ERROR + INTERNAL_ERROR); - getroom(&CC->room, hold_rm); + cprintf("%d Internal error: cannot allocate memory.\n", ERROR + INTERNAL_ERROR); + CtdlGetRoom(&CC->room, hold_rm); return; } @@ -1511,13 +1499,13 @@ void ical_freebusy(char *who) { icalcomponent_set_method(fb, ICAL_METHOD_PUBLISH); /* Set the DTSTAMP to right now. */ - icalcomponent_set_dtstamp(fb, icaltime_from_timet(time(NULL), 0)); + icalcomponent_set_dtstamp(fb, icaltime_from_timet_with_zone(time(NULL), 0, icaltimezone_get_utc_timezone())); /* Add the user's email address as ORGANIZER */ sprintf(buf, "MAILTO:%s", who); if (strchr(buf, '@') == NULL) { strcat(buf, "@"); - strcat(buf, config.c_fqdn); + strcat(buf, CtdlGetConfigStr("c_fqdn")); } for (i=0; buf[i]; ++i) { if (buf[i]==' ') buf[i] = '_'; @@ -1525,36 +1513,36 @@ 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, "calendar: adding busy time from events"); CtdlForEachMessage(MSGS_ALL, 0, NULL, NULL, NULL, ical_freebusy_backend, (void *)fb ); /* If values for DTSTART and DTEND are still not present, set them * to yesterday and tomorrow as default values. */ if (icalcomponent_get_first_property(fb, ICAL_DTSTART_PROPERTY) == NULL) { - icalcomponent_set_dtstart(fb, icaltime_from_timet(time(NULL)-86400L, 0)); + icalcomponent_set_dtstart(fb, icaltime_from_timet_with_zone(time(NULL)-86400L, 0, icaltimezone_get_utc_timezone())); } if (icalcomponent_get_first_property(fb, ICAL_DTEND_PROPERTY) == NULL) { - icalcomponent_set_dtend(fb, icaltime_from_timet(time(NULL)+86400L, 0)); + icalcomponent_set_dtend(fb, icaltime_from_timet_with_zone(time(NULL)+86400L, 0, icaltimezone_get_utc_timezone())); } /* Put the freebusy component into the calendar component */ - CtdlLogPrintf(CTDL_DEBUG, "Encapsulating\n"); + syslog(LOG_DEBUG, "calendar: encapsulating"); 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, "calendar: setting method"); icalcomponent_set_method(encaps, ICAL_METHOD_PUBLISH); /* Serialize it */ - CtdlLogPrintf(CTDL_DEBUG, "Serializing\n"); + syslog(LOG_DEBUG, "calendar: serializing"); serialized_request = icalcomponent_as_ical_string_r(encaps); icalcomponent_free(encaps); /* Don't need this anymore. */ @@ -1566,11 +1554,10 @@ 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); } - /* * Backend for ical_getics() * @@ -1587,18 +1574,17 @@ void ical_getics_backend(long msgnum, void *data) { /* Look for the calendar event... */ - msg = CtdlFetchMessage(msgnum, 1); + msg = CtdlFetchMessage(msgnum, 1, 1); if (msg == NULL) return; memset(&ird, 0, sizeof ird); strcpy(ird.desired_partnum, "_HUNT_"); - mime_parser(msg->cm_fields['M'], - NULL, - *ical_locate_part, /* callback function */ - NULL, NULL, - (void *) &ird, /* user data */ - 0 + mime_parser(CM_RANGE(msg, eMesageText), + *ical_locate_part, /* callback function */ + NULL, NULL, + (void *) &ird, /* user data */ + 0 ); - CtdlFreeMessage(msg); + CM_Free(msg); if (ird.cal == NULL) return; @@ -1645,7 +1631,6 @@ void ical_getics_backend(long msgnum, void *data) { } - /* * Retrieve all of the calendar items in the current room, and output them * as a single icalendar object. @@ -1663,7 +1648,7 @@ void ical_getics(void) encaps = icalcomponent_new_vcalendar(); if (encaps == NULL) { - CtdlLogPrintf(CTDL_ALERT, "ERROR: could not allocate component!\n"); + syslog(LOG_ERR, "calendar: could not allocate component!"); cprintf("%d Could not allocate memory\n", ERROR+INTERNAL_ERROR); return; } @@ -1706,7 +1691,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); } } @@ -1741,7 +1726,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"), CtdlGetConfigLong("c_maxmsglen"), NULL, 0); if (calstream == NULL) { return; } @@ -1789,7 +1774,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, "calendar: attaching timezone '%s'", (char*) Value); icaltimezone *t = NULL; /* First look for a timezone attached to the original calendar */ @@ -1854,10 +1839,8 @@ void cmd_ical(char *argbuf) } if (!strcasecmp(subcmd, "sgi")) { - CIT_ICAL->server_generated_invitations = - (extract_int(argbuf, 1) ? 1 : 0) ; - cprintf("%d %d\n", - CIT_OK, CIT_ICAL->server_generated_invitations); + CIT_ICAL->server_generated_invitations = (extract_int(argbuf, 1) ? 1 : 0) ; + cprintf("%d %d\n", CIT_OK, CIT_ICAL->server_generated_invitations); return; } @@ -1900,26 +1883,25 @@ 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_ERR, "calendar: couldn't get the user calendar room"); 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); @@ -1927,16 +1909,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_ERR, "calendar: couldn't get the user calendar room!"); 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); @@ -1944,16 +1926,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_ERR, "calendar: couldn't get the user calendar room!"); 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); @@ -1978,7 +1960,7 @@ void ical_send_out_invitations(icalcomponent *top_level_cal, icalcomponent *cal) icalcomponent *encaps = NULL; char *request_message_text = NULL; struct CtdlMessage *msg = NULL; - struct recptypes *valid = NULL; + recptypes *valid = NULL; char attendees_string[SIZ]; int num_attendees = 0; char this_attendee[256]; @@ -1988,18 +1970,19 @@ 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, "calendar: trying to reply to NULL event?"); return; } - /* If this is a VCALENDAR component, look for a VEVENT subcomponent. */ if (icalcomponent_isa(cal) == ICAL_VCALENDAR_COMPONENT) { ical_send_out_invitations(top_level_cal, @@ -2013,7 +1996,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, "calendar: cannot clone calendar object"); return; } @@ -2032,24 +2015,22 @@ void ical_send_out_invitations(icalcomponent *top_level_cal, icalcomponent *cal) /* Determine who the recipients of this message are (the attendees) */ strcpy(attendees_string, ""); for (attendee = icalcomponent_get_first_property(the_request, ICAL_ATTENDEE_PROPERTY); attendee != NULL; attendee = icalcomponent_get_next_property(the_request, ICAL_ATTENDEE_PROPERTY)) { - if (icalproperty_get_attendee(attendee)) { - safestrncpy(this_attendee, icalproperty_get_attendee(attendee), sizeof this_attendee); - if (!strncasecmp(this_attendee, "MAILTO:", 7)) { - strcpy(this_attendee, &this_attendee[7]); - - if (!CtdlIsMe(this_attendee, sizeof this_attendee)) { /* don't send an invitation to myself! */ - snprintf(&attendees_string[strlen(attendees_string)], - sizeof(attendees_string) - strlen(attendees_string), - "%s, ", - this_attendee + const char *ch = icalproperty_get_attendee(attendee); + if ((ch != NULL) && !strncasecmp(ch, "MAILTO:", 7)) { + safestrncpy(this_attendee, ch + 7, sizeof(this_attendee)); + + if (!CtdlIsMe(this_attendee, sizeof this_attendee)) { /* don't send an invitation to myself! */ + snprintf(&attendees_string[strlen(attendees_string)], + sizeof(attendees_string) - strlen(attendees_string), + "%s, ", + this_attendee ); - ++num_attendees; - } + ++num_attendees; } } } - CtdlLogPrintf(CTDL_DEBUG, "<%d> attendees: <%s>\n", num_attendees, attendees_string); + syslog(LOG_DEBUG, "calendar: <%d> attendees: <%s>", 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! @@ -2062,7 +2043,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_ALERT, "ERROR: could not allocate component!\n"); + syslog(LOG_ERR, "calendar: could not allocate component!"); icalcomponent_free(the_request); return; } @@ -2097,6 +2078,15 @@ void ical_send_out_invitations(icalcomponent *top_level_cal, icalcomponent *cal) ) { t = icalproperty_get_dtstart(p); // it's safe to use dtstart for all of them + /* 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)) { z = icaltimezone_get_utc_timezone(); @@ -2106,21 +2096,13 @@ void ical_send_out_invitations(icalcomponent *top_level_cal, icalcomponent *cal) } /* 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) && (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) && (tzidc)) { + z = icaltimezone_get_builtin_timezone_from_tzid(tzidc); } if (z) { @@ -2138,8 +2120,7 @@ void ical_send_out_invitations(icalcomponent *top_level_cal, icalcomponent *cal) attached_zones[num_zones_attached++] = z; } - icalproperty_set_parameter(p, - icalparameter_new_tzid(icaltimezone_get_tzid(z)) + icalproperty_set_parameter(p, icalparameter_new_tzid(icaltimezone_get_tzid(z)) ); } } @@ -2171,21 +2152,25 @@ 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); CtdlSubmitMsg(msg, valid, "", QP_EADDR); - CtdlFreeMessage(msg); + CM_Free(msg); free_recipients(valid); } } @@ -2209,7 +2194,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, "calendar: ical_saving_vevent() has been called"); /* Don't send out invitations unless the client wants us to. */ if (CIT_ICAL->server_generated_invitations == 0) { @@ -2258,7 +2243,6 @@ void ical_saving_vevent(icalcomponent *top_level_cal, icalcomponent *cal) { } - /* * Back end for ical_obj_beforesave() * This hunts for the UID of the calendar event (becomes Citadel msg EUID), @@ -2269,10 +2253,10 @@ void ical_obj_beforesave_backend(char *name, char *filename, char *partnum, char *disp, void *content, char *cbtype, char *cbcharset, size_t length, char *encoding, char *cbid, void *cbuserdata) { + const char* pch; icalcomponent *cal, *nested_event, *nested_todo, *whole_cal; icalproperty *p; char new_uid[256] = ""; - char buf[1024] = ""; struct CtdlMessage *msg = (struct CtdlMessage *) cbuserdata; if (!msg) return; @@ -2318,13 +2302,10 @@ void ical_obj_beforesave_backend(char *name, char *filename, char *partnum, p = ical_ctdl_get_subprop(cal, ICAL_UID_PROPERTY); } if (p != NULL) { - safestrncpy(buf, icalproperty_get_comment(p), sizeof buf); - if (!IsEmptyStr(buf)) { - if (msg->cm_fields['E'] != NULL) { - free(msg->cm_fields['E']); - } - msg->cm_fields['E'] = strdup(buf); - CtdlLogPrintf(CTDL_DEBUG, "Saving calendar UID <%s>\n", buf); + pch = icalproperty_get_comment(p); + if (!IsEmptyStr(pch)) { + CM_SetField(msg, eExclusiveID, pch, strlen(pch)); + syslog(LOG_DEBUG, "calendar: saving calendar UID <%s>", pch); } } @@ -2332,12 +2313,12 @@ void ical_obj_beforesave_backend(char *name, char *filename, char *partnum, p = ical_ctdl_get_subprop(cal, ICAL_SUMMARY_PROPERTY); if (p != NULL) { - safestrncpy(buf, icalproperty_get_comment(p), sizeof buf); - if (!IsEmptyStr(buf)) { - if (msg->cm_fields['U'] != NULL) { - free(msg->cm_fields['U']); - } - msg->cm_fields['U'] = strdup(buf); + pch = icalproperty_get_comment(p); + if (!IsEmptyStr(pch)) { + char *subj; + + subj = rfc2047encode(pch, strlen(pch)); + CM_SetAsField(msg, eMsgSubject, &subj, strlen(subj)); } } @@ -2348,11 +2329,7 @@ void ical_obj_beforesave_backend(char *name, char *filename, char *partnum, time_t idtstart; idtstart = icaltime_as_timet(icalproperty_get_dtstart(p)); if (idtstart > 0) { - if (msg->cm_fields['T'] != NULL) { - free(msg->cm_fields['T']); - } - msg->cm_fields['T'] = strdup("000000000000000000"); - sprintf(msg->cm_fields['T'], "%ld", idtstart); + CM_SetFieldLONG(msg, eTimestamp, idtstart); } } @@ -2365,8 +2342,6 @@ void ical_obj_beforesave_backend(char *name, char *filename, char *partnum, } - - /* * See if we need to prevent the object from being saved (we don't allow * MIME types other than text/calendar in "calendar" or "tasks" rooms). @@ -2374,7 +2349,7 @@ void ical_obj_beforesave_backend(char *name, char *filename, char *partnum, * If the message is being saved, we also set various message header fields * using data found in the iCalendar object. */ -int ical_obj_beforesave(struct CtdlMessage *msg) +int ical_obj_beforesave(struct CtdlMessage *msg, recptypes *recp) { /* First determine if this is a calendar or tasks room */ if ( (CC->room.QRdefaultview != VIEW_CALENDAR) @@ -2385,22 +2360,21 @@ 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, "calendar: rejecting non-RFC822 message"); return(1); /* You tried to save a non-RFC822 message! */ } - if (msg->cm_fields['M'] == NULL) { + if (CM_IsEmpty(msg, eMesageText)) { return(1); /* You tried to save a null message! */ } /* Do all of our lovely back-end parsing */ - mime_parser(msg->cm_fields['M'], - NULL, - *ical_obj_beforesave_backend, - NULL, NULL, - (void *)msg, - 0 - ); + mime_parser(CM_RANGE(msg, eMesageText), + *ical_obj_beforesave_backend, + NULL, NULL, + (void *)msg, + 0 + ); return(0); } @@ -2442,7 +2416,7 @@ void ical_obj_aftersave_backend(char *name, char *filename, char *partnum, * (This will start back end tasks such as automatic generation of invitations, * if such actions are appropriate.) */ -int ical_obj_aftersave(struct CtdlMessage *msg) +int ical_obj_aftersave(struct CtdlMessage *msg, recptypes *recp) { char roomname[ROOMNAMELEN]; @@ -2451,7 +2425,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. */ } @@ -2460,16 +2434,15 @@ int ical_obj_aftersave(struct CtdlMessage *msg) if (msg->cm_format_type != 4) return(1); /* Reject null messages */ - if (msg->cm_fields['M'] == NULL) return(1); + if (CM_IsEmpty(msg, eMesageText)) return(1); /* Now recurse through it looking for our icalendar data */ - mime_parser(msg->cm_fields['M'], - NULL, - *ical_obj_aftersave_backend, - NULL, NULL, - NULL, - 0 - ); + mime_parser(CM_RANGE(msg, eMesageText), + *ical_obj_aftersave_backend, + NULL, NULL, + NULL, + 0 + ); return(0); } @@ -2480,6 +2453,7 @@ void ical_session_startup(void) { memset(CIT_ICAL, 0, sizeof(struct cit_ical)); } + void ical_session_shutdown(void) { free(CIT_ICAL); } @@ -2488,12 +2462,11 @@ void ical_session_shutdown(void) { /* * Back end for ical_fixed_output() */ -void ical_fixed_output_backend(icalcomponent *cal, - int recursion_level -) { +void ical_fixed_output_backend(icalcomponent *cal, int recursion_level) { icalcomponent *c; icalproperty *p; char buf[256]; + const char *ch; p = icalcomponent_get_first_property(cal, ICAL_SUMMARY_PROPERTY); if (p != NULL) { @@ -2512,11 +2485,12 @@ void ical_fixed_output_backend(icalcomponent *cal, /* If the component has attendees, iterate through them. */ for (p = icalcomponent_get_first_property(cal, ICAL_ATTENDEE_PROPERTY); (p != NULL); p = icalcomponent_get_next_property(cal, ICAL_ATTENDEE_PROPERTY)) { - safestrncpy(buf, icalproperty_get_attendee(p), sizeof buf); - if (!strncasecmp(buf, "MAILTO:", 7)) { + ch = icalproperty_get_attendee(p); + if ((ch != NULL) && + !strncasecmp(ch, "MAILTO:", 7)) { /* screen name or email address */ - strcpy(buf, &buf[7]); + safestrncpy(buf, ch + 7, sizeof(buf)); striplt(buf); cprintf("%s ", buf); } @@ -2533,7 +2507,6 @@ void ical_fixed_output_backend(icalcomponent *cal, } - /* * Function to output iCalendar data as plain text. Nobody uses MSG0 * anymore, so really this is just so we expose the vCard data to the full @@ -2559,12 +2532,11 @@ void ical_fixed_output(char *ptr, int len) { } - -void serv_calendar_destroy(void) -{ +void serv_calendar_destroy(void) { icaltimezone_free_builtin_timezones(); } + /* * Register this module with the Citadel server. */ @@ -2574,7 +2546,12 @@ CTDL_MODULE_INIT(calendar) { /* Tell libical to return errors instead of aborting if it gets bad data */ + +#ifdef LIBICAL_ICAL_EXPORT // cheap and sleazy way to detect libical >=2.0 + icalerror_set_errors_are_fatal(0); +#else icalerror_errors_are_fatal = 0; +#endif /* Use our own application prefix in tzid's generated from system tzdata */ icaltimezone_set_tzid_prefix("/citadel.org/"); @@ -2582,15 +2559,15 @@ 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); - CtdlRegisterProtoHook(cmd_ical, "ICAL", "Citadel iCal commands"); - CtdlRegisterSessionHook(ical_session_startup, EVT_START); - CtdlRegisterSessionHook(ical_session_shutdown, EVT_STOP); + CtdlRegisterSessionHook(ical_CtdlCreateRoom, EVT_LOGIN, PRIO_LOGIN + 1); + CtdlRegisterProtoHook(cmd_ical, "ICAL", "Citadel iCalendar commands"); + CtdlRegisterSessionHook(ical_session_startup, EVT_START, PRIO_START + 1); + CtdlRegisterSessionHook(ical_session_shutdown, EVT_STOP, PRIO_STOP + 80); CtdlRegisterFixedOutputHook("text/calendar", ical_fixed_output); CtdlRegisterFixedOutputHook("application/ics", ical_fixed_output); CtdlRegisterCleanupHook(serv_calendar_destroy); } - - /* return our Subversion id for the Log */ - return "$Id$"; + + /* return our module name for the log */ + return "calendar"; }