X-Git-Url: https://code.citadel.org/?a=blobdiff_plain;f=webcit%2Fevent.c;h=7433e53120ed2c99007772b6fa03ef64f3539344;hb=8e165dd308679f195af8614d62dbdb4e43238495;hp=859c4d5ea1e30162a53386502713e610835d6e14;hpb=4ea562633e7454d0adfa7fef991a91fb184c71af;p=citadel.git
diff --git a/webcit/event.c b/webcit/event.c
index 859c4d5ea..7433e5312 100644
--- a/webcit/event.c
+++ b/webcit/event.c
@@ -1,23 +1,21 @@
/*
* $Id$
+ *
+ * Editing calendar events.
*/
-/**
- * \defgroup EditCal Editing calendar events.
- * \ingroup Calendaring
- */
-/*@{*/
+
#include "webcit.h"
#include "webserver.h"
+#include "calendar.h"
-
-#ifdef WEBCIT_WITH_CALENDAR_SERVICE
-
-/**
- * \brief Display an event by itself (for editing)
- * \param supplied_vevent the event to edit
- * \param msgnum reference on the citserver
+/*
+ * Display an event by itself (for editing)
+ * supplied_vevent the event to edit
+ * msgnum reference on the citserver
*/
-void display_edit_individual_event(icalcomponent *supplied_vevent, long msgnum) {
+void display_edit_individual_event(icalcomponent *supplied_vevent, long msgnum, char *from,
+ int unread, calview *calv)
+{
icalcomponent *vevent;
icalproperty *p;
icalvalue *v;
@@ -31,20 +29,97 @@ void display_edit_individual_event(icalcomponent *supplied_vevent, long msgnum)
char attendee_string[SIZ];
char buf[SIZ];
int organizer_is_me = 0;
- int i;
+ int i, j = 0;
int sequence = 0;
+ char weekday_labels[7][32];
+ char month_labels[12][32];
+ long weekstart = 0;
+ icalproperty *rrule = NULL;
+ struct icalrecurrencetype recur;
+ char weekday_is_selected[7];
+ int which_rrmonthtype_is_preselected = 0;
+
+ int rrmday;
+ int rrmweekday;
+
+ icaltimetype day1;
+ int weekbase;
+ int rrmweek;
+ int rrymweek;
+ int rrymweekday;
+ int rrymonth;
+ int which_rrend_is_preselected;
+ int which_rryeartype_is_preselected;
+
+
+ char *tabnames[3];
+ const char *frequency_units[8];
+ const char *ordinals[6];
+
+ frequency_units[0] = _("seconds");
+ frequency_units[1] = _("minutes");
+ frequency_units[2] = _("hours");
+ frequency_units[3] = _("days");
+ frequency_units[4] = _("weeks");
+ frequency_units[5] = _("months");
+ frequency_units[6] = _("years");
+ frequency_units[7] = _("never");
+
+
+ ordinals[0] = "0";
+ ordinals[1] = _("first");
+ ordinals[2] = _("second");
+ ordinals[3] = _("third");
+ ordinals[4] = _("fourth");
+ ordinals[5] = _("fifth");
+
+
+ tabnames[0] = _("Event");
+ tabnames[1] = _("Attendees");
+ tabnames[2] = _("Recurrence");
+
+ get_pref_long("weekstart", &weekstart, 17);
+ if (weekstart > 6) weekstart = 0;
lprintf(9, "display_edit_individual_event(%ld) calview=%s year=%s month=%s day=%s\n",
msgnum, bstr("calview"), bstr("year"), bstr("month"), bstr("day")
);
+ /* populate the weekday names - begin */
+ now = time(NULL);
+ localtime_r(&now, &tm_now);
+ while (tm_now.tm_wday != 0) {
+ now -= 86400L;
+ localtime_r(&now, &tm_now);
+ }
+ for (i=0; i<7; ++i) {
+ localtime_r(&now, &tm_now);
+ wc_strftime(weekday_labels[i], 32, "%A", &tm_now);
+ now += 86400L;
+ }
+ /* populate the weekday names - end */
+
+ /* populate the month names - begin */
+ now = 259200L; /* 1970-jan-04 is the first Sunday ever */
+ localtime_r(&now, &tm_now);
+ for (i=0; i<12; ++i) {
+ localtime_r(&now, &tm_now);
+ wc_strftime(month_labels[i], 32, "%B", &tm_now);
+ now += 2678400L;
+ }
+ /* populate the month names - end */
+
now = time(NULL);
strcpy(organizer_string, "");
strcpy(attendee_string, "");
if (supplied_vevent != NULL) {
vevent = supplied_vevent;
- /**
+
+ /* Convert all timestamps to UTC to make them easier to process. */
+ ical_dezonify(vevent);
+
+ /*
* If we're looking at a fully encapsulated VCALENDAR
* rather than a VEVENT component, attempt to use the first
* relevant VEVENT subcomponent. If there is none, the
@@ -55,8 +130,8 @@ void display_edit_individual_event(icalcomponent *supplied_vevent, long msgnum)
if (icalcomponent_isa(vevent) == ICAL_VCALENDAR_COMPONENT) {
display_edit_individual_event(
icalcomponent_get_first_component(
- vevent, ICAL_VEVENT_COMPONENT
- ), msgnum
+ vevent, ICAL_VEVENT_COMPONENT),
+ msgnum, from, unread, NULL
);
return;
}
@@ -66,107 +141,81 @@ void display_edit_individual_event(icalcomponent *supplied_vevent, long msgnum)
created_new_vevent = 1;
}
- /** Learn the sequence */
+ /* Learn the sequence */
p = icalcomponent_get_first_property(vevent, ICAL_SEQUENCE_PROPERTY);
if (p != NULL) {
sequence = icalproperty_get_sequence(p);
}
- /** Begin output */
+ /* Begin output */
output_headers(1, 1, 2, 0, 0, 0);
- wprintf("
\n");
-
- wprintf("\n"
- );
+ wc_printf("
\n");
+ wc_printf("
");
+ wc_printf(_("Add or edit an event"));
+ wc_printf("
");
+ wc_printf("\n");
+ wc_printf("
\n");
- wprintf("
\n");
- wprintf("\n"
+ wc_printf("
\n"); /* end 'fix_scrollbar_bug' div */
+
+ StrBufAppendPrintf(WC->trailing_javascript,
+ "eventEditAllDay(); \n"
+ "RecurrenceShowHide(); \n"
+ "EnableOrDisableCheckButton(); \n"
);
-
address_book_popup();
wDumpContent(1);
@@ -423,12 +773,14 @@ void display_edit_individual_event(icalcomponent *supplied_vevent, long msgnum)
}
}
-/**
- * \brief Save an edited event
- * \param supplied_vevent the event to save
- * \param msgnum the index on the citserver
+/*
+ * Save an edited event
+ *
+ * supplied_vevent: the event to save
+ * msgnum: the index on the citserver
*/
-void save_individual_event(icalcomponent *supplied_vevent, long msgnum) {
+void save_individual_event(icalcomponent *supplied_vevent, long msgnum, char *from,
+ int unread, calview *calv) {
char buf[SIZ];
icalproperty *prop;
icalcomponent *vevent, *encaps;
@@ -446,7 +798,11 @@ void save_individual_event(icalcomponent *supplied_vevent, long msgnum) {
if (supplied_vevent != NULL) {
vevent = supplied_vevent;
- /**
+
+ /* Convert all timestamps to UTC to make them easier to process. */
+ ical_dezonify(vevent);
+
+ /*
* If we're looking at a fully encapsulated VCALENDAR
* rather than a VEVENT component, attempt to use the first
* relevant VEVENT subcomponent. If there is none, the
@@ -457,8 +813,8 @@ void save_individual_event(icalcomponent *supplied_vevent, long msgnum) {
if (icalcomponent_isa(vevent) == ICAL_VCALENDAR_COMPONENT) {
save_individual_event(
icalcomponent_get_first_component(
- vevent, ICAL_VEVENT_COMPONENT
- ), msgnum
+ vevent, ICAL_VEVENT_COMPONENT),
+ msgnum, from, unread, NULL
);
return;
}
@@ -468,10 +824,10 @@ void save_individual_event(icalcomponent *supplied_vevent, long msgnum) {
created_new_vevent = 1;
}
- if ( (!IsEmptyStr(bstr("save_button")))
- || (!IsEmptyStr(bstr("check_button"))) ) {
+ if ( (havebstr("save_button"))
+ || (havebstr("check_button")) ) {
- /** Replace values in the component with ones from the form */
+ /* Replace values in the component with ones from the form */
while (prop = icalcomponent_get_first_property(vevent,
ICAL_SUMMARY_PROPERTY), prop != NULL) {
@@ -479,13 +835,17 @@ void save_individual_event(icalcomponent *supplied_vevent, long msgnum) {
icalproperty_free(prop);
}
- if (!IsEmptyStr(bstr("summary"))) {
-
+ /* Add NOW() to the calendar object... */
+ icalcomponent_set_dtstamp(vevent,
+ icaltime_from_timet(
+ time(NULL), 0));
+
+ if (havebstr("summary")) {
icalcomponent_add_property(vevent,
icalproperty_new_summary(bstr("summary")));
} else {
icalcomponent_add_property(vevent,
- icalproperty_new_summary("Untitled Event"));
+ icalproperty_new_summary(_("Untitled Event")));
}
while (prop = icalcomponent_get_first_property(vevent,
@@ -493,7 +853,7 @@ void save_individual_event(icalcomponent *supplied_vevent, long msgnum) {
icalcomponent_remove_property(vevent, prop);
icalproperty_free(prop);
}
- if (!IsEmptyStr(bstr("location"))) {
+ if (havebstr("location")) {
icalcomponent_add_property(vevent,
icalproperty_new_location(bstr("location")));
}
@@ -502,7 +862,7 @@ void save_individual_event(icalcomponent *supplied_vevent, long msgnum) {
icalcomponent_remove_property(vevent, prop);
icalproperty_free(prop);
}
- if (!IsEmptyStr(bstr("description"))) {
+ if (havebstr("description")) {
icalcomponent_add_property(vevent,
icalproperty_new_description(bstr("description")));
}
@@ -513,7 +873,7 @@ void save_individual_event(icalcomponent *supplied_vevent, long msgnum) {
icalproperty_free(prop);
}
- if (!strcmp(bstr("alldayevent"), "yes")) {
+ if (yesbstr("alldayevent")) {
all_day_event = 1;
}
else {
@@ -527,16 +887,10 @@ void save_individual_event(icalcomponent *supplied_vevent, long msgnum) {
icaltime_from_webform(&event_start, "dtstart");
}
- /**
- * The following odd-looking snippet of code looks like it
- * takes some unnecessary steps. It is done this way because
- * libical incorrectly turns an "all day event" into a normal
- * event starting at midnight (i.e. it serializes as date/time
- * instead of just date) unless icalvalue_new_date() is used.
- * So we force it, if this is an all day event.
- */
prop = icalproperty_new_dtstart(event_start);
+
if (all_day_event) {
+ /* Force it to serialize as a date-only rather than date/time */
icalproperty_set_value(prop, icalvalue_new_date(event_start));
}
@@ -554,16 +908,106 @@ void save_individual_event(icalcomponent *supplied_vevent, long msgnum) {
icalproperty_free(prop);
}
- if (all_day_event == 0) {
+ if (all_day_event) {
+ icaltime_from_webform_dateonly(&t, "dtend");
+
+ /* with this field supposed to be non-inclusive we have to add one day */
+ icaltime_adjust(&t, 1, 0, 0, 0);
+ }
+ else {
icaltime_from_webform(&t, "dtend");
- icalcomponent_add_property(vevent,
- icalproperty_new_dtend(icaltime_normalize(t)
- )
- );
}
- /** See if transparency is indicated */
- if (!IsEmptyStr(bstr("transp"))) {
+ icalcomponent_add_property(vevent,
+ icalproperty_new_dtend(icaltime_normalize(t)
+ )
+ );
+
+ /* recurrence rules -- begin */
+
+ /* remove any existing rule */
+ while (prop = icalcomponent_get_first_property(vevent, ICAL_RRULE_PROPERTY), prop != NULL) {
+ icalcomponent_remove_property(vevent, prop);
+ icalproperty_free(prop);
+ }
+
+ if (yesbstr("is_recur")) {
+ struct icalrecurrencetype recur;
+ icalrecurrencetype_clear(&recur);
+
+ recur.interval = atoi(bstr("interval"));
+ recur.freq = atoi(bstr("freq"));
+
+ switch(recur.freq) {
+
+ /* These can't happen; they're disabled. */
+ case ICAL_SECONDLY_RECURRENCE:
+ break;
+ case ICAL_MINUTELY_RECURRENCE:
+ break;
+ case ICAL_HOURLY_RECURRENCE:
+ break;
+
+ /* Daily is valid but there are no further inputs. */
+ case ICAL_DAILY_RECURRENCE:
+ break;
+
+ /* These are the real options. */
+
+ case ICAL_WEEKLY_RECURRENCE:
+ j=0;
+ for (i=0; i<7; ++i) {
+ snprintf(buf, sizeof buf, "weekday%d", i);
+ if (YESBSTR(buf)) recur.by_day[j++] =
+ icalrecurrencetype_day_day_of_week(i+1);
+ }
+ recur.by_day[j++] = ICAL_RECURRENCE_ARRAY_MAX;
+ break;
+
+ case ICAL_MONTHLY_RECURRENCE:
+ if (!strcasecmp(bstr("rrmonthtype"), "rrmonthtype_mday")) {
+ recur.by_month_day[0] = event_start.day;
+ recur.by_month_day[1] = ICAL_RECURRENCE_ARRAY_MAX;
+ }
+ else if (!strcasecmp(bstr("rrmonthtype"), "rrmonthtype_wday")) {
+ recur.by_day[0] = (atoi(bstr("rrmweek")) * 8)
+ + atoi(bstr("rrmweekday")) + 1;
+ recur.by_day[1] = ICAL_RECURRENCE_ARRAY_MAX;
+ }
+ break;
+
+ case ICAL_YEARLY_RECURRENCE:
+ if (!strcasecmp(bstr("rryeartype"), "rryeartype_ymday")) {
+ /* no further action is needed here */
+ }
+ else if (!strcasecmp(bstr("rryeartype"), "rryeartype_ywday")) {
+ recur.by_month[0] = atoi(bstr("rrymonth"));
+ recur.by_month[1] = ICAL_RECURRENCE_ARRAY_MAX;
+ recur.by_day[0] = (atoi(bstr("rrymweek")) * 8)
+ + atoi(bstr("rrymweekday")) + 1;
+ recur.by_day[1] = ICAL_RECURRENCE_ARRAY_MAX;
+ }
+ break;
+
+ /* This one can't happen either. */
+ case ICAL_NO_RECURRENCE:
+ break;
+ }
+
+ if (!strcasecmp(bstr("rrend"), "rrend_count")) {
+ recur.count = atoi(bstr("rrcount"));
+ }
+ else if (!strcasecmp(bstr("rrend"), "rrend_until")) {
+ icaltime_from_webform_dateonly(&recur.until, "rruntil");
+ }
+
+ icalcomponent_add_property(vevent, icalproperty_new_rrule(recur));
+ }
+
+ /* recurrence rules -- end */
+
+ /* See if transparency is indicated */
+ if (havebstr("transp")) {
if (!strcasecmp(bstr("transp"), "opaque")) {
formtransp = ICAL_TRANSP_OPAQUE;
}
@@ -580,14 +1024,14 @@ void save_individual_event(icalcomponent *supplied_vevent, long msgnum) {
icalcomponent_add_property(vevent, icalproperty_new_transp(formtransp));
}
- /** Give this event a UID if it doesn't have one. */
+ /* Give this event a UID if it doesn't have one. */
if (icalcomponent_get_first_property(vevent,
ICAL_UID_PROPERTY) == NULL) {
generate_uuid(buf);
icalcomponent_add_property(vevent, icalproperty_new_uid(buf));
}
- /** Increment the sequence ID */
+ /* Increment the sequence ID */
while (prop = icalcomponent_get_first_property(vevent,
ICAL_SEQUENCE_PROPERTY), (prop != NULL) ) {
i = icalproperty_get_sequence(prop);
@@ -600,7 +1044,7 @@ void save_individual_event(icalcomponent *supplied_vevent, long msgnum) {
icalproperty_new_sequence(sequence)
);
- /**
+ /*
* Set the organizer, only if one does not already exist *and*
* the form is supplying one
*/
@@ -609,7 +1053,7 @@ void save_individual_event(icalcomponent *supplied_vevent, long msgnum) {
ICAL_ORGANIZER_PROPERTY) == NULL)
&& (!IsEmptyStr(buf)) ) {
- /** set new organizer */
+ /* set new organizer */
sprintf(organizer_string, "MAILTO:%s", buf);
icalcomponent_add_property(vevent,
icalproperty_new_organizer(organizer_string)
@@ -617,13 +1061,13 @@ void save_individual_event(icalcomponent *supplied_vevent, long msgnum) {
}
- /**
+ /*
* Add any new attendees listed in the web form
*/
/* First, strip out the parenthesized partstats. */
strcpy(form_attendees, bstr("attendees"));
- stripout(form_attendees, '(', ')');
+ while ( stripout(form_attendees, '(', ')') != 0);
/* Next, change any commas to newlines, because we want newline-separated attendees. */
j = strlen(form_attendees);
@@ -636,7 +1080,7 @@ void save_individual_event(icalcomponent *supplied_vevent, long msgnum) {
}
}
- /** Now iterate! */
+ /* Now iterate! */
for (i=0; i
ImportantMessage, &buf[4]);
}
+ icalmemory_free_ring ();
icalcomponent_free(encaps);
+ encaps = NULL;
}
- /** Or, check attendee availability if the user asked for that. */
- if ( (encaps != NULL) && (!IsEmptyStr(bstr("check_button"))) ) {
+ /* Or, check attendee availability if the user asked for that. */
+ if ( (encaps != NULL) && (havebstr("check_button")) ) {
- /** Call this function, which does the real work */
+ /* Call this function, which does the real work */
check_attendee_availability(encaps);
- /** This displays the form again, with our annotations */
- display_edit_individual_event(encaps, msgnum);
+ /* This displays the form again, with our annotations */
+ display_edit_individual_event(encaps, msgnum, from, unread, NULL);
icalcomponent_free(encaps);
+ encaps = NULL;
+ }
+ if (encaps != NULL) {
+ icalcomponent_free(encaps);
+ encaps = NULL;
}
}
- /**
+ /*
* If the user clicked 'Delete' then delete it.
*/
- if ( (!IsEmptyStr(bstr("delete_button"))) && (msgnum > 0L) ) {
- serv_printf("DELE %ld", atol(bstr("msgnum")));
+ if ( (havebstr("delete_button")) && (msgnum > 0L) ) {
+ serv_printf("DELE %ld", lbstr("msgnum"));
serv_getln(buf, sizeof buf);
}
@@ -739,13 +1190,13 @@ STARTOVER: for (attendee = icalcomponent_get_first_property(vevent, ICAL_ATTENDE
icalcomponent_free(vevent);
}
- /** If this was a save or delete, go back to the calendar view. */
- if (IsEmptyStr(bstr("check_button"))) {
- readloop("readfwd");
+ /* If this was a save or delete, go back to the calendar or summary view. */
+ if (!havebstr("check_button")) {
+ if (!strcasecmp(bstr("calview"), "summary")) {
+ summary();
+ }
+ else {
+ readloop(readfwd);
+ }
}
}
-
-
-#endif /* WEBCIT_WITH_CALENDAR_SERVICE */
-
-/*@}*/