X-Git-Url: https://code.citadel.org/?a=blobdiff_plain;f=webcit%2Fcalendar_tools.c;h=86da183b8abcca7f6a8666b7e2b99a1ae1142fc5;hb=HEAD;hp=be8e16f98f45f4dc66c02e5f520230d6a0778713;hpb=63f3ada05b99ec1994ab72cb0c8c0f44cd0f33c7;p=citadel.git diff --git a/webcit/calendar_tools.c b/webcit/calendar_tools.c index be8e16f98..488296ca7 100644 --- a/webcit/calendar_tools.c +++ b/webcit/calendar_tools.c @@ -1,42 +1,23 @@ /* - * $Id$ - */ -/** - * \defgroup MiscCal Miscellaneous functions which handle calendar components. + * Miscellaneous functions which handle calendar components. + * + * Copyright (c) 1996-2012 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. */ -/*@{*/ + #include "webcit.h" -#include "webserver.h" - -/* \todo FIXME ... this needs to be internationalized */ -/** Month Strings. */ -char *months[] = { - "January", - "February", - "March", - "April", - "May", - "June", - "July", - "August", - "September", - "October", - "November", - "December" -}; -/** Day Strings */ -char *days[] = { - "Sunday", - "Monday", - "Tuesday", - "Wednesday", - "Thursday", - "Friday", - "Saturday" -}; +#include "time.h" +#include "calendar.h" -/** Hour strings */ +/* Hour strings */ char *hourname[] = { "12am", "1am", "2am", "3am", "4am", "5am", "6am", "7am", "8am", "9am", "10am", "11am", "12pm", @@ -44,10 +25,7 @@ char *hourname[] = { "7pm", "8pm", "9pm", "10pm", "11pm" }; -#ifdef WEBCIT_WITH_CALENDAR_SERVICE - -/** - * \brief display and edit date/time +/* * The display_icaltimetype_as_webform() and icaltime_from_webform() functions * handle the display and editing of date/time properties in web pages. The * first one converts an icaltimetype into valid HTML markup -- a series of form @@ -58,31 +36,27 @@ char *hourname[] = { * property (for example, a start and end time) by ensuring the field names are * unique within the form. * - * \todo NOTE: These functions assume that the icaltimetype being edited is in UTC, and + * NOTE: These functions assume that the icaltimetype being edited is in UTC, and * will convert to/from local time for editing. "local" in this case is assumed * to be the time zone in which the WebCit server is running. A future improvement * might be to allow the user to specify his/her timezone. - * \param t the time we want to parse - * \param prefix ???? \todo */ - -void display_icaltimetype_as_webform(struct icaltimetype *t, char *prefix) { +void display_icaltimetype_as_webform(struct icaltimetype *t, char *prefix, int date_only) { + wcsession *WCC = WC; int i; time_t now; struct tm tm_now; - int this_year; time_t tt; struct tm tm; - const int span = 10; int all_day_event = 0; - char calhourformat[16]; - - get_preference("calhourformat", calhourformat, sizeof calhourformat); + int time_format; + char timebuf[32]; + + time_format = get_time_format_cached (); now = time(NULL); localtime_r(&now, &tm_now); - this_year = tm_now.tm_year + 1900; if (t == NULL) return; if (t->is_date) all_day_event = 1; @@ -94,129 +68,114 @@ void display_icaltimetype_as_webform(struct icaltimetype *t, char *prefix) { localtime_r(&tt, &tm); } - wprintf(_("Month: ")); - wprintf("\n"); - - wprintf(_("Day: ")); - wprintf("\n"); - - wprintf(_("Year: ")); - wprintf("WBuf, prefix, -1, 0); + wc_printf("\" id=\""); + StrBufAppendBufPlain(WCC->WBuf, prefix, -1, 0); + wc_printf("\" size=\"10\" maxlength=\"10\" value=\""); + wc_strftime(timebuf, 32, "%Y-%m-%d", &tm); + StrBufAppendBufPlain(WCC->WBuf, timebuf, -1, 0); + wc_printf("\">"); + + StrBufAppendPrintf(WC->trailing_javascript, "attachDatePicker('"); + StrBufAppendPrintf(WC->trailing_javascript, prefix); + StrBufAppendPrintf(WC->trailing_javascript, "', '%s');\n", get_selected_language()); + + /* If we're editing a date only, we still generate the time boxes, but we hide them. + * This keeps the data model consistent. + */ + if (date_only) { + wc_printf("
"); } - wprintf("\n"); - wprintf(_("Hour: ")); - wprintf("\n", prefix); for (i=0; i<=23; ++i) { - if (!strcasecmp(calhourformat, "24")) { - wprintf("\n", + if (time_format == WC_TIMEFORMAT_24) { + wc_printf("\n", ((tm.tm_hour == i) ? "SELECTED" : ""), i, i - ); + ); } else { - wprintf("\n", + wc_printf("\n", ((tm.tm_hour == i) ? "SELECTED" : ""), i, hourname[i] - ); + ); } } - wprintf("\n"); + wc_printf("\n"); - wprintf(_("Minute: ")); - wprintf("\n", prefix); for (i=0; i<=59; ++i) { if ( (i % 5 == 0) || (tm.tm_min == i) ) { - wprintf("\n", + wc_printf("\n", ((tm.tm_min == i) ? "SELECTED" : ""), i, i - ); + ); } } - wprintf("\n"); + wc_printf("\n"); + + if (date_only) { + wc_printf("
"); + } } -/** - *\brief Get time from form - * get the time back from the user and convert it into internal structs. - * \param t our time element - * \param prefix whats that\todo ???? +/* + * Get date/time from a web form and convert it into an icaltimetype struct. */ void icaltime_from_webform(struct icaltimetype *t, char *prefix) { - char vname[32]; - time_t tt; - struct tm tm; - struct icaltimetype t2; - - tt = time(NULL); - localtime_r(&tt, &tm); - - sprintf(vname, "%s_month", prefix); tm.tm_mon = atoi(bstr(vname)) - 1; - sprintf(vname, "%s_day", prefix); tm.tm_mday = atoi(bstr(vname)); - sprintf(vname, "%s_year", prefix); tm.tm_year = atoi(bstr(vname)) - 1900; - sprintf(vname, "%s_hour", prefix); tm.tm_hour = atoi(bstr(vname)); - sprintf(vname, "%s_minute", prefix); tm.tm_min = atoi(bstr(vname)); - - tt = mktime(&tm); - t2 = icaltime_from_timet(tt, 0); - memcpy(t, &t2, sizeof(struct icaltimetype)); + char vname[32]; + + if (!t) return; + + /* Stuff with zero values */ + memset(t, 0, sizeof(struct icaltimetype)); + + /* Get the year/month/date all in one shot -- it will be in ISO YYYY-MM-DD format */ + sscanf((char*)BSTR(prefix), "%04d-%02d-%02d", &t->year, &t->month, &t->day); + + /* hour */ + sprintf(vname, "%s_hour", prefix); + t->hour = IBSTR(vname); + + /* minute */ + sprintf(vname, "%s_minute", prefix); + t->minute = IBSTR(vname); + + /* time zone is set to the default zone for this server */ + t->is_date = 0; + t->zone = get_default_icaltimezone(); } -/** - *\brief Get time from form - * get the time back from the user and convert it into internal structs. - * \param t our time element - * \param prefix whats that\todo ???? - */ +/* + * Get date (no time) from a web form and convert it into an icaltimetype struct. + */ void icaltime_from_webform_dateonly(struct icaltimetype *t, char *prefix) { - char vname[32]; + if (!t) return; + /* Stuff with zero values */ memset(t, 0, sizeof(struct icaltimetype)); - sprintf(vname, "%s_month", prefix); t->month = atoi(bstr(vname)); - sprintf(vname, "%s_day", prefix); t->day = atoi(bstr(vname)); - sprintf(vname, "%s_year", prefix); t->year = atoi(bstr(vname)); - t->is_utc = 1; + /* Get the year/month/date all in one shot -- it will be in ISO YYYY-MM-DD format */ + sscanf((char*)BSTR(prefix), "%04d-%02d-%02d", &t->year, &t->month, &t->day); + + /* time zone is set to the default zone for this server */ + t->zone = icaltimezone_get_utc_timezone(); t->is_date = 1; } -/** - * \brief Render PAPSTAT +/* * Render a PARTSTAT parameter as a string (and put it in parentheses) - * \param buf the string to put it to - * \param attendee the attendee to textify */ void partstat_as_string(char *buf, icalproperty *attendee) { icalparameter *partstat_param; @@ -225,99 +184,140 @@ void partstat_as_string(char *buf, icalproperty *attendee) { strcpy(buf, _("(status unknown)")); partstat_param = icalproperty_get_first_parameter( - attendee, - ICAL_PARTSTAT_PARAMETER - ); + attendee, + ICAL_PARTSTAT_PARAMETER + ); if (partstat_param == NULL) { return; } partstat = icalparameter_get_partstat(partstat_param); switch(partstat) { - case ICAL_PARTSTAT_X: - strcpy(buf, "(x)"); - break; - case ICAL_PARTSTAT_NEEDSACTION: - strcpy(buf, _("(needs action)")); - break; - case ICAL_PARTSTAT_ACCEPTED: - strcpy(buf, _("(accepted)")); - break; - case ICAL_PARTSTAT_DECLINED: - strcpy(buf, _("(declined)")); - break; - case ICAL_PARTSTAT_TENTATIVE: - strcpy(buf, _("(tenative)")); - break; - case ICAL_PARTSTAT_DELEGATED: - strcpy(buf, _("(delegated)")); - break; - case ICAL_PARTSTAT_COMPLETED: - strcpy(buf, _("(completed)")); - break; - case ICAL_PARTSTAT_INPROCESS: - strcpy(buf, _("(in process)")); - break; - case ICAL_PARTSTAT_NONE: - strcpy(buf, _("(none)")); - break; + case ICAL_PARTSTAT_X: + strcpy(buf, "(x)"); + break; + case ICAL_PARTSTAT_NEEDSACTION: + strcpy(buf, _("(needs action)")); + break; + case ICAL_PARTSTAT_ACCEPTED: + strcpy(buf, _("(accepted)")); + break; + case ICAL_PARTSTAT_DECLINED: + strcpy(buf, _("(declined)")); + break; + case ICAL_PARTSTAT_TENTATIVE: + strcpy(buf, _("(tenative)")); + break; + case ICAL_PARTSTAT_DELEGATED: + strcpy(buf, _("(delegated)")); + break; + case ICAL_PARTSTAT_COMPLETED: + strcpy(buf, _("(completed)")); + break; + case ICAL_PARTSTAT_INPROCESS: + strcpy(buf, _("(in process)")); + break; + case ICAL_PARTSTAT_NONE: + strcpy(buf, _("(none)")); + break; } } - -/** - * \brief embedd - * Utility function to encapsulate a subcomponent into a full VCALENDAR - * \param subcomp the component to encapsulate - * \returns the meta object ??? +/* + * Utility function to encapsulate a subcomponent into a full VCALENDAR. + * + * We also scan for any date/time properties that reference timezones, and attach + * those timezones along with the supplied subcomponent. (Increase the size of the array if you need to.) + * + * Note: if you change anything here, change it in Citadel server's ical_send_out_invitations() too. */ icalcomponent *ical_encapsulate_subcomponent(icalcomponent *subcomp) { icalcomponent *encaps; - - /* lprintf(9, "ical_encapsulate_subcomponent() called\n"); */ + icalproperty *p; + struct icaltimetype t; + const icaltimezone *attached_zones[5] = { NULL, NULL, NULL, NULL, NULL }; + int i; + const icaltimezone *z; + int num_zones_attached = 0; + int zone_already_attached; if (subcomp == NULL) { - lprintf(3, "ERROR: called with NULL argument!\n"); + syslog(LOG_WARNING, "ERROR: ical_encapsulate_subcomponent() called with NULL argument\n"); return NULL; } - /** - * If we're already looking at a full VCALENDAR component, - * don't bother ... just return itself. + /* + * If we're already looking at a full VCALENDAR component, this is probably an error. */ if (icalcomponent_isa(subcomp) == ICAL_VCALENDAR_COMPONENT) { + syslog(LOG_WARNING, "ERROR: component sent to ical_encapsulate_subcomponent() already top level\n"); return subcomp; } - /** Encapsulate the VEVENT component into a complete VCALENDAR */ + /* search for... */ + for (p = icalcomponent_get_first_property(subcomp, ICAL_ANY_PROPERTY); + p != NULL; + p = icalcomponent_get_next_property(subcomp, ICAL_ANY_PROPERTY)) + { + if ( (icalproperty_isa(p) == ICAL_COMPLETED_PROPERTY) + || (icalproperty_isa(p) == ICAL_CREATED_PROPERTY) + || (icalproperty_isa(p) == ICAL_DATEMAX_PROPERTY) + || (icalproperty_isa(p) == ICAL_DATEMIN_PROPERTY) + || (icalproperty_isa(p) == ICAL_DTEND_PROPERTY) + || (icalproperty_isa(p) == ICAL_DTSTAMP_PROPERTY) + || (icalproperty_isa(p) == ICAL_DTSTART_PROPERTY) + || (icalproperty_isa(p) == ICAL_DUE_PROPERTY) + || (icalproperty_isa(p) == ICAL_EXDATE_PROPERTY) + || (icalproperty_isa(p) == ICAL_LASTMODIFIED_PROPERTY) + || (icalproperty_isa(p) == ICAL_MAXDATE_PROPERTY) + || (icalproperty_isa(p) == ICAL_MINDATE_PROPERTY) + || (icalproperty_isa(p) == ICAL_RECURRENCEID_PROPERTY) + ) { + t = icalproperty_get_dtstart(p); /*/ it's safe to use dtstart for all of them */ + if ((icaltime_is_valid_time(t)) && (z=icaltime_get_timezone(t), z)) { + + zone_already_attached = 0; + for (i=0; i<5; ++i) { + if (z == attached_zones[i]) { + ++zone_already_attached; + syslog(LOG_DEBUG, "zone already attached!!\n"); + } + } + if ((!zone_already_attached) && (num_zones_attached < 5)) { + syslog(LOG_DEBUG, "attaching zone %d!\n", num_zones_attached); + attached_zones[num_zones_attached++] = z; + } + + icalproperty_set_parameter(p, + icalparameter_new_tzid(icaltimezone_get_tzid((icaltimezone *)z)) + ); + } + } + } + + /* Encapsulate the VEVENT component into a complete VCALENDAR */ encaps = icalcomponent_new(ICAL_VCALENDAR_COMPONENT); if (encaps == NULL) { - lprintf(3, "%s:%d: Error - could not allocate component!\n", - __FILE__, __LINE__); + syslog(LOG_WARNING, "ERROR: ical_encapsulate_subcomponent() could not allocate component\n"); return NULL; } - /** Set the Product ID */ + /* Set the Product ID */ icalcomponent_add_property(encaps, icalproperty_new_prodid(PRODID)); - /** Set the Version Number */ + /* Set the Version Number */ icalcomponent_add_property(encaps, icalproperty_new_version("2.0")); - /** Encapsulate the subcomponent inside */ - /* lprintf(9, "Doing the encapsulation\n"); */ - icalcomponent_add_component(encaps, subcomp); + /* Attach any timezones we need */ + if (num_zones_attached > 0) for (i=0; i