+++ /dev/null
-/*
- * $Id$
- */
-/**
- *
- * \defgroup WebcitAuth WebcitAuth; Handles authentication of users to a Citadel server.
- * \ingroup CitadelConfig
- */
-
-/*@{*/
-#include "webcit.h"
-
-
-
-/**
- * \brief user states
- * the plain text states of a user. filled in at \ function TODO initialize_ax_defs()
- * due to NLS
- */
-char *axdefs[7];
-
-void initialize_axdefs(void) {
- axdefs[0] = _("Deleted"); /*!0: an erased user */
- axdefs[1] = _("New User"); /*!1: a new user */
- axdefs[2] = _("Problem User"); /*!2: a trouble maker */
- axdefs[3] = _("Local User"); /*!3: user with normal privileges */
- axdefs[4] = _("Network User"); /*!4: a user that may access network resources */
- axdefs[5] = _("Preferred User");/*!5: a moderator */
- axdefs[6] = _("Aide"); /*!6: chief */
-}
-
-
-
-
-/**
- * \brief Display the login screen
- * \param mesg The error message if last attempt failed.
- */
-void display_login(char *mesg)
-{
- char buf[SIZ];
-
- output_headers(1, 1, 2, 0, 0, 0);
- wprintf("<div style=\"position:absolute; top:20px; left:20px; right:20px\">\n");
-
- if (mesg != NULL) if (strlen(mesg) > 0) {
- stresc(buf, mesg, 0, 0);
- svprintf("mesg", WCS_STRING, "%s", buf);
- }
-
- svprintf("LOGIN_INSTRUCTIONS", WCS_STRING,
- _("<ul>"
- "<li><b>If you already have an account on %s</b>, "
- "enter your user name and password and click "Login." "
- "<li><b>If you are a new user</b>, enter the name and password "
- "you wish to use, "
- "and click "New User." "
- "<li>Please log off properly when finished. "
- "<li>You must use a browser that supports <i>frames</i> and "
- "<i>cookies</i>. "
- "<li>Also keep in mind that if your browser is "
- "configured to block pop-up windows, you will not be able "
- "to receive any instant messages.<br />"
- "</ul>"),
- serv_info.serv_humannode
- );
-
- svprintf("USERNAME_BOX", WCS_STRING, "%s", _("User name:"));
- svprintf("PASSWORD_BOX", WCS_STRING, "%s", _("Password:"));
- svprintf("LANGUAGE_BOX", WCS_STRING, "%s", _("Language:"));
- svprintf("LOGIN_BUTTON", WCS_STRING, "%s", _("Login"));
- svprintf("NEWUSER_BUTTON", WCS_STRING, "%s", _("New User"));
- svprintf("EXIT_BUTTON", WCS_STRING, "%s", _("Exit"));
- svprintf("hello", WCS_SERVCMD, "MESG hello");
- svprintf("BOXTITLE", WCS_STRING, _("%s - powered by Citadel"),
- serv_info.serv_humannode);
- svcallback("DO_LANGUAGE_BOX", offer_languages);
- if (serv_info.serv_newuser_disabled) {
- svprintf("NEWUSER_BUTTON_PRE", WCS_STRING, "<div style=\"display:none;\">");
- svprintf("NEWUSER_BUTTON_POST", WCS_STRING, "</div>");
- }
- else {
- svprintf("NEWUSER_BUTTON_PRE", WCS_STRING, "");
- svprintf("NEWUSER_BUTTON_POST", WCS_STRING, "");
- }
-
- do_template("login");
-
- wDumpContent(2);
-}
-
-
-
-
-/** \brief Initialize the session
- * This function needs to get called whenever the session changes from
- * not-logged-in to logged-in, either by an explicit login by the user or
- * by a timed-out session automatically re-establishing with a little help
- * from the browser cookie. Either way, we need to load access controls and
- * preferences from the server.
- *
- * \param user the username
- * \param pass his password
- * \param serv_response The parameters returned from a Citadel USER or NEWU command
- */
-void become_logged_in(char *user, char *pass, char *serv_response)
-{
- char buf[SIZ];
-
- WC->logged_in = 1;
- extract_token(WC->wc_fullname, &serv_response[4], 0, '|', sizeof WC->wc_fullname);
- safestrncpy(WC->wc_username, user, sizeof WC->wc_username);
- safestrncpy(WC->wc_password, pass, sizeof WC->wc_password);
- WC->axlevel = extract_int(&serv_response[4], 1);
- if (WC->axlevel >= 6) {
- WC->is_aide = 1;
- }
-
- load_preferences();
-
- serv_puts("CHEK");
- serv_getln(buf, sizeof buf);
- if (buf[0] == '2') {
- WC->new_mail = extract_int(&buf[4], 0);
- WC->need_regi = extract_int(&buf[4], 1);
- WC->need_vali = extract_int(&buf[4], 2);
- extract_token(WC->cs_inet_email, &buf[4], 3, '|', sizeof WC->cs_inet_email);
- }
-
- get_preference("current_iconbar", buf, sizeof buf);
- WC->current_iconbar = atoi(buf);
-
- get_preference("floordiv_expanded", WC->floordiv_expanded, sizeof WC->floordiv_expanded);
-}
-
-
-/**
- * \brief Login Checks
- * the logics to detect invalid passwords not to get on citservers nerves
- */
-void do_login(void)
-{
- char buf[SIZ];
-
- if (strlen(bstr("language")) > 0) {
- set_selected_language(bstr("language"));
- go_selected_language();
- }
-
- if (strlen(bstr("exit_action")) > 0) {
- do_logout();
- return;
- }
- if (strlen(bstr("login_action")) > 0) {
- serv_printf("USER %s", bstr("name"));
- serv_getln(buf, sizeof buf);
- if (buf[0] == '3') {
- serv_printf("PASS %s", bstr("pass"));
- serv_getln(buf, sizeof buf);
- if (buf[0] == '2') {
- become_logged_in(bstr("name"),
- bstr("pass"), buf);
- } else {
- display_login(&buf[4]);
- return;
- }
- } else {
- display_login(&buf[4]);
- return;
- }
- }
- if (strlen(bstr("newuser_action")) > 0) {
- if (strlen(bstr("pass")) == 0) {
- display_login(_("Blank passwords are not allowed."));
- return;
- }
- serv_printf("NEWU %s", bstr("name"));
- serv_getln(buf, sizeof buf);
- if (buf[0] == '2') {
- become_logged_in(bstr("name"), bstr("pass"), buf);
- serv_printf("SETP %s", bstr("pass"));
- serv_getln(buf, sizeof buf);
- } else {
- display_login(&buf[4]);
- return;
- }
- }
- if (WC->logged_in) {
- if (WC->need_regi) {
- display_reg(1);
- } else {
- do_welcome();
- }
- } else {
- display_login(_("Your password was not accepted."));
- }
-
-}
-
-/**
- * \brief display the user a welcome screen.
- * if this is the first time login, and the web based setup is enabled,
- * lead the user through the setup routines
- */
-void do_welcome(void)
-{
- char buf[SIZ];
-#ifdef XXX_NOT_FINISHED_YET_XXX
- FILE *fp;
- int i;
-
- /**
- * See if we have to run the first-time setup wizard
- */
- if (WC->is_aide) {
- if (!setup_wizard) {
- sprintf(wizard_filename, "setupwiz.%s.%s",
- ctdlhost, ctdlport);
- for (i=0; i<strlen(wizard_filename); ++i) {
- if ( (wizard_filename[i]==' ')
- || (wizard_filename[i] == '/')
- ) {
- wizard_filename[i] = '_';
- }
- }
-
- fp = fopen(wizard_filename, "r");
- if (fp != NULL) {
- fgets(buf, sizeof buf, fp);
- buf[strlen(buf)-1] = 0;
- fclose(fp);
- if (atoi(buf) == serv_info.serv_rev_level) {
- setup_wizard = 1; /**< already run */
- }
- }
- }
-
- if (!setup_wizard) {
- http_redirect("setup_wizard");
- }
- }
-#endif
-
- /**
- * Go to the user's preferred start page
- */
- get_preference("startpage", buf, sizeof buf);
- if (strlen(buf)==0) {
- safestrncpy(buf, "dotskip&room=_BASEROOM_", sizeof buf);
- set_preference("startpage", buf, 1);
- }
- if (buf[0] == '/') {
- strcpy(buf, &buf[1]);
- }
- http_redirect(buf);
-}
-
-
-/**
- * Disconnect from the Citadel server, and end this WebCit session
- */
-void end_webcit_session(void) {
- char buf[256];
-
- if (WC->logged_in) {
- sprintf(buf, "%d", WC->current_iconbar);
- set_preference("current_iconbar", buf, 0);
- set_preference("floordiv_expanded", WC->floordiv_expanded, 1);
- }
-
- serv_puts("QUIT");
- WC->killthis = 1;
- /* close() of citadel socket will be done by do_housekeeping() */
-}
-
-/**
- * execute the logout
- */
-void do_logout(void)
-{
- char buf[SIZ];
-
- safestrncpy(WC->wc_username, "", sizeof WC->wc_username);
- safestrncpy(WC->wc_password, "", sizeof WC->wc_password);
- safestrncpy(WC->wc_roomname, "", sizeof WC->wc_roomname);
- safestrncpy(WC->wc_fullname, "", sizeof WC->wc_fullname);
-
- /** Calling output_headers() this way causes the cookies to be un-set */
- output_headers(1, 1, 0, 1, 0, 0);
-
- wprintf("<center>");
- serv_puts("MESG goodbye");
- serv_getln(buf, sizeof buf);
-
- if (WC->serv_sock >= 0) {
- if (buf[0] == '1') {
- fmout("CENTER");
- } else {
- wprintf("Goodbye\n");
- }
- }
- else {
- wprintf(_("This program was unable to connect or stay "
- "connected to the Citadel server. Please report "
- "this problem to your system administrator.")
- );
- }
-
- wprintf("<hr /><a href=\".\">");
- wprintf(_("Log in again"));
- wprintf("</A> "
- "<a href=\"javascript:window.close();\">");
- wprintf(_("Close window"));
- wprintf("</a></center>\n");
- wDumpContent(2);
- end_webcit_session();
-}
-
-
-/* *
- * validate new users
- */
-void validate(void)
-{
- char cmd[SIZ];
- char user[SIZ];
- char buf[SIZ];
- int a;
-
- output_headers(1, 1, 2, 0, 0, 0);
- wprintf("<div id=\"banner\">\n"
- "<TABLE WIDTH=100%% BORDER=0 BGCOLOR=\"#444455\"><TR><TD>"
- "<SPAN CLASS=\"titlebar\">");
- wprintf(_("Validate new users"));
- wprintf("</SPAN></TD></TR></TABLE>\n</div>\n<div id=\"content\">\n");
-
- /** If the user just submitted a validation, process it... */
- safestrncpy(buf, bstr("user"), sizeof buf);
- if (strlen(buf) > 0) {
- if (strlen(bstr("axlevel")) > 0) {
- serv_printf("VALI %s|%s", buf, bstr("axlevel"));
- serv_getln(buf, sizeof buf);
- if (buf[0] != '2') {
- wprintf("<b>%s</b><br />\n", &buf[4]);
- }
- }
- }
-
- /** Now see if any more users require validation. */
- serv_puts("GNUR");
- serv_getln(buf, sizeof buf);
- if (buf[0] == '2') {
- wprintf("<b>");
- wprintf(_("No users require validation at this time."));
- wprintf("</b><br />\n");
- wDumpContent(1);
- return;
- }
- if (buf[0] != '3') {
- wprintf("<b>%s</b><br />\n", &buf[4]);
- wDumpContent(1);
- return;
- }
-
- wprintf("<div class=\"fix_scrollbar_bug\">"
- "<table border=0 width=100%% bgcolor=\"#ffffff\"><tr><td>\n");
- wprintf("<center>");
-
- safestrncpy(user, &buf[4], sizeof user);
- serv_printf("GREG %s", user);
- serv_getln(cmd, sizeof cmd);
- if (cmd[0] == '1') {
- a = 0;
- do {
- serv_getln(buf, sizeof buf);
- ++a;
- if (a == 1)
- wprintf("#%s<br /><H1>%s</H1>",
- buf, &cmd[4]);
- if (a == 2)
- wprintf("PW: %s<br />\n", buf);
- if (a == 3)
- wprintf("%s<br />\n", buf);
- if (a == 4)
- wprintf("%s<br />\n", buf);
- if (a == 5)
- wprintf("%s, ", buf);
- if (a == 6)
- wprintf("%s ", buf);
- if (a == 7)
- wprintf("%s<br />\n", buf);
- if (a == 8)
- wprintf("%s<br />\n", buf);
- if (a == 9)
- wprintf(_("Current access level: %d (%s)\n"),
- atoi(buf), axdefs[atoi(buf)]);
- } while (strcmp(buf, "000"));
- } else {
- wprintf("<H1>%s</H1>%s<br />\n", user, &cmd[4]);
- }
-
- wprintf("<hr />");
- wprintf(_("Select access level for this user:"));
- wprintf("<br />\n");
- for (a = 0; a <= 6; ++a) {
- wprintf("<a href=\"validate&user=");
- urlescputs(user);
- wprintf("&axlevel=%d\">%s</A> \n",
- a, axdefs[a]);
- }
- wprintf("<br />\n");
-
- wprintf("</CENTER>\n");
- wprintf("</td></tr></table></div>\n");
- wDumpContent(1);
-}
-
-
-
-/**
- * \brief Display form for registration.
- * (Set during_login to 1 if this registration is being performed during
- * new user login and will require chaining to the proper screen.)
- * \param during_login are we just in the login phase?
- */
-void display_reg(int during_login)
-{
- long vcard_msgnum;
-
- if (goto_config_room() != 0) {
- if (during_login) do_welcome();
- else display_main_menu();
- return;
- }
-
- vcard_msgnum = locate_user_vcard(WC->wc_fullname, -1);
- if (vcard_msgnum < 0L) {
- if (during_login) do_welcome();
- else display_main_menu();
- return;
- }
-
- if (during_login) {
- do_edit_vcard(vcard_msgnum, "1", "do_welcome");
- }
- else {
- do_edit_vcard(vcard_msgnum, "1", "display_main_menu");
- }
-
-}
-
-
-
-
-/**
- * display form for changing your password
- */
-void display_changepw(void)
-{
- char buf[SIZ];
-
- output_headers(1, 1, 2, 0, 0, 0);
- wprintf("<div id=\"banner\">\n"
- "<TABLE WIDTH=100%% BORDER=0 BGCOLOR=\"#444455\"><TR><TD>"
- "<SPAN CLASS=\"titlebar\">");
- wprintf(_("Change your password"));
- wprintf("</SPAN>"
- "</TD></TR></TABLE>\n"
- "</div>\n<div id=\"content\">\n"
- );
-
- if (strlen(WC->ImportantMessage) > 0) {
- do_template("beginbox_nt");
- wprintf("<SPAN CLASS=\"errormsg\">"
- "%s</SPAN><br />\n", WC->ImportantMessage);
- do_template("endbox");
- safestrncpy(WC->ImportantMessage, "", sizeof WC->ImportantMessage);
- }
-
- wprintf("<div class=\"fix_scrollbar_bug\">"
- "<table border=0 width=100%% bgcolor=\"#ffffff\"><tr><td>\n");
-
- wprintf("<CENTER><br />");
- serv_puts("MESG changepw");
- serv_getln(buf, sizeof buf);
- if (buf[0] == '1') {
- fmout("CENTER");
- }
-
- wprintf("<form name=\"changepwform\" action=\"changepw\" method=\"post\">\n");
- wprintf("<CENTER>"
- "<table border=\"0\" cellspacing=\"5\" cellpadding=\"5\" "
- "BGCOLOR=\"#EEEEEE\">"
- "<TR><TD>");
- wprintf(_("Enter new password:"));
- wprintf("</TD>\n");
- wprintf("<TD><INPUT TYPE=\"password\" NAME=\"newpass1\" VALUE=\"\" MAXLENGTH=\"20\"></TD></TR>\n");
- wprintf("<TR><TD>");
- wprintf(_("Enter it again to confirm:"));
- wprintf("</TD>\n");
- wprintf("<TD><INPUT TYPE=\"password\" NAME=\"newpass2\" VALUE=\"\" MAXLENGTH=\"20\"></TD></TR>\n");
-
- wprintf("</TABLE><br />\n");
- wprintf("<INPUT type=\"submit\" name=\"change_action\" value=\"%s\">", _("Change password"));
- wprintf(" ");
- wprintf("<INPUT type=\"submit\" name=\"cancel_action\" value=\"%s\">\n", _("Cancel"));
- wprintf("</form></center>\n");
- wprintf("</td></tr></table></div>\n");
- wDumpContent(1);
-}
-
-/**
- * \brief change password
- * if passwords match, propagate it to citserver.
- */
-void changepw(void)
-{
- char buf[SIZ];
- char newpass1[32], newpass2[32];
-
- if (strlen(bstr("change_action")) == 0) {
- safestrncpy(WC->ImportantMessage,
- _("Cancelled. Password was not changed."),
- sizeof WC->ImportantMessage);
- display_main_menu();
- return;
- }
-
- safestrncpy(newpass1, bstr("newpass1"), sizeof newpass1);
- safestrncpy(newpass2, bstr("newpass2"), sizeof newpass2);
-
- if (strcasecmp(newpass1, newpass2)) {
- safestrncpy(WC->ImportantMessage,
- _("They don't match. Password was not changed."),
- sizeof WC->ImportantMessage);
- display_changepw();
- return;
- }
-
- if (strlen(newpass1) == 0) {
- safestrncpy(WC->ImportantMessage,
- _("Blank passwords are not allowed."),
- sizeof WC->ImportantMessage);
- display_changepw();
- return;
- }
-
- serv_printf("SETP %s", newpass1);
- serv_getln(buf, sizeof buf);
- sprintf(WC->ImportantMessage, "%s", &buf[4]);
- if (buf[0] == '2') {
- safestrncpy(WC->wc_password, buf, sizeof WC->wc_password);
- display_main_menu();
- }
- else {
- display_changepw();
- }
-}
-
-
-
-/** @} */
+++ /dev/null
-/*
- * $Id$
- *//**
- * \defgroup AjaxAutoCompletion ajax-powered autocompletion...
- * \ingroup ClientPower
- */
-
-/*@{*/
-#include "webcit.h"
-
-/**
- * \brief Recipient autocompletion results
- * \param partial the account to search for ??????
- */
-void recp_autocomplete(char *partial) {
- char buf[1024];
- char name[128];
-
- output_headers(0, 0, 0, 0, 0, 0);
-
- wprintf("Content-type: text/html\r\n"
- "Server: %s\r\n"
- "Connection: close\r\n"
- "Pragma: no-cache\r\n"
- "Cache-Control: no-store\r\n",
- SERVER);
- begin_burst();
-
- wprintf("<ul>");
-
- serv_printf("AUTO %s", partial);
- serv_getln(buf, sizeof buf);
- if (buf[0] == '1') {
- while(serv_getln(buf, sizeof buf), strcmp(buf, "000")) {
- extract_token(name, buf, 0, '|', sizeof name);
- wprintf("<li>");
- escputs(name);
- wprintf("</li>");
- }
- }
-
- wprintf("</ul>");
-
- wprintf("\r\n\r\n");
- wDumpContent(0);
-}
-
-
-/** @} */
+++ /dev/null
-/*
- * $Id$
- */
-/**
- *
- * \defgroup CalendarAv Check attendee availability for scheduling a meeting.
- * \ingroup Calendaring
- */
-/*@{*/
-
-
-#include "webcit.h"
-#include "webserver.h"
-
-/** only available if we have calendaring */
-#ifdef WEBCIT_WITH_CALENDAR_SERVICE
-
-
-
-/**
- * \brief verify users avaiability
- * Utility function to fetch a VFREEBUSY type of thing for
- * any specified user.
- * \param who string of the user to search
- */
-icalcomponent *get_freebusy_for_user(char *who) {
- char buf[SIZ];
- char *serialized_fb = NULL;
- icalcomponent *fb = NULL;
-
- serv_printf("ICAL freebusy|%s", who);
- serv_getln(buf, sizeof buf);
- if (buf[0] == '1') {
- serialized_fb = read_server_text();
- }
-
- if (serialized_fb == NULL) {
- return NULL;
- }
-
- fb = icalcomponent_new_from_string(serialized_fb);
- free(serialized_fb);
- if (fb == NULL) {
- return NULL;
- }
-
- return(fb);
-}
-
-
-
-
-/**
- * \brief Check if dates are overlapping
- * Check to see if two events overlap.
- * (This function is used in both Citadel and WebCit. If you change it in
- * one place, change it in the other. Better yet, put it in a library.)
- * \param t1start date one start
- * \param t1end date one end
- * \param t2start date one start
- * \param t2end date two end
- * \returns nonzero if they do.
- */
-int ical_ctdl_is_overlap(
- struct icaltimetype t1start,
- struct icaltimetype t1end,
- 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 (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);
- }
- }
- }
-
- /** Now check for overlaps using date *and* time. */
-
- /** 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 1 ends before event 2 starts, we're in the clear. */
- if (icaltime_compare(t1end, t2start) <= 0) return(0);
-
- /** If event 2 ends before event 1 starts, we're also ok. */
- if (icaltime_compare(t2end, t1start) <= 0) return(0);
-
- /** Otherwise, they overlap. */
- return(1);
-}
-
-
-
-/*
- * \brief dig availability on citserver
- * Back end function for check_attendee_availability()
- * This one checks an individual attendee against a supplied
- * event start and end time. All these fields have already been
- * broken out.
- * \param attendee_string name of the attendee
- * \param event_start starttime of the event to check
- * \param event_end endtime of the event to check
- * \return The result is placed in 'annotation'.
- */
-void check_individual_attendee(char *attendee_string,
- struct icaltimetype event_start,
- struct icaltimetype event_end,
- char *annotation) {
-
- icalcomponent *fbc = NULL;
- icalcomponent *fb = NULL;
- icalproperty *thisfb = NULL;
- struct icalperiodtype period;
-
- /**
- * Set to 'unknown' right from the beginning. Unless we learn
- * something else, that's what we'll go with.
- */
- strcpy(annotation, _("availability unknown"));
-
- fbc = get_freebusy_for_user(attendee_string);
- if (fbc == NULL) {
- return;
- }
-
- /**
- * Make sure we're looking at a VFREEBUSY by itself. What we're probably
- * looking at initially is a VFREEBUSY encapsulated in a VCALENDAR.
- */
- if (icalcomponent_isa(fbc) == ICAL_VCALENDAR_COMPONENT) {
- fb = icalcomponent_get_first_component(fbc, ICAL_VFREEBUSY_COMPONENT);
- }
- else if (icalcomponent_isa(fbc) == ICAL_VFREEBUSY_COMPONENT) {
- fb = fbc;
- }
-
- /** Iterate through all FREEBUSY's looking for conflicts. */
- if (fb != NULL) {
-
- strcpy(annotation, _("free"));
-
- for (thisfb = icalcomponent_get_first_property(fb, ICAL_FREEBUSY_PROPERTY);
- thisfb != NULL;
- thisfb = icalcomponent_get_next_property(fb, ICAL_FREEBUSY_PROPERTY) ) {
-
- /** Do the check */
- period = icalproperty_get_freebusy(thisfb);
- if (ical_ctdl_is_overlap(period.start, period.end,
- event_start, event_end)) {
- strcpy(annotation, _("BUSY"));
- }
-
- }
- }
-
- icalcomponent_free(fbc);
-}
-
-
-
-
-/**
- * \brief check attendees availability
- * Check the availability of all attendees for an event (when possible)
- * and annotate accordingly.
- * \param vevent the event which should be compared with attendees calendar
- */
-void check_attendee_availability(icalcomponent *vevent) {
- icalproperty *attendee = NULL;
- icalproperty *dtstart_p = NULL;
- icalproperty *dtend_p = NULL;
- struct icaltimetype dtstart_t;
- struct icaltimetype dtend_t;
- char attendee_string[SIZ];
- char annotated_attendee_string[SIZ];
- char annotation[SIZ];
-
- if (vevent == NULL) {
- return;
- }
-
- /**
- * 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
- * NULL returned by icalcomponent_get_first_component() will
- * tell the next iteration of this function to create a
- * new one.
- */
- if (icalcomponent_isa(vevent) == ICAL_VCALENDAR_COMPONENT) {
- check_attendee_availability(
- icalcomponent_get_first_component(
- vevent, ICAL_VEVENT_COMPONENT
- )
- );
- return;
- }
-
- ical_dezonify(vevent); /**< Convert everything to UTC */
-
- /**
- * Learn the start and end times.
- */
- dtstart_p = icalcomponent_get_first_property(vevent, ICAL_DTSTART_PROPERTY);
- if (dtstart_p != NULL) dtstart_t = icalproperty_get_dtstart(dtstart_p);
-
- dtend_p = icalcomponent_get_first_property(vevent, ICAL_DTEND_PROPERTY);
- if (dtend_p != NULL) dtend_t = icalproperty_get_dtend(dtend_p);
-
- /**
- * Iterate through attendees.
- */
- for (attendee = icalcomponent_get_first_property(vevent, ICAL_ATTENDEE_PROPERTY);
- attendee != NULL;
- attendee = icalcomponent_get_next_property(vevent, ICAL_ATTENDEE_PROPERTY)) {
-
- strcpy(attendee_string, icalproperty_get_attendee(attendee));
- if (!strncasecmp(attendee_string, "MAILTO:", 7)) {
-
- /** screen name or email address */
- strcpy(attendee_string, &attendee_string[7]);
- striplt(attendee_string);
-
- check_individual_attendee(attendee_string,
- dtstart_t, dtend_t,
- annotation);
-
- /** Replace the attendee name with an annotated one. */
- snprintf(annotated_attendee_string, sizeof annotated_attendee_string,
- "MAILTO:%s (%s)", attendee_string, annotation);
- icalproperty_set_attendee(attendee, annotated_attendee_string);
-
- }
- }
-
-}
-
-
-#endif /* WEBCIT_WITH_CALENDAR_SERVICE */
-
-/** @} */
+++ /dev/null
-/*
- * $Id$
- */
-/**
- * \defgroup calav Functions which handle calendar objects and their processing/display.
- * \ingroup Calendaring
- */
-/* @{ */
-
-#include "webcit.h"
-#include "webserver.h"
-
-#ifndef WEBCIT_WITH_CALENDAR_SERVICE
-
-/**
- * \brief get around non existing types
- * Handler stubs for builds with no calendar library available
- * \param part_source dummy pointer to the source
- * \param msgnum number of the mesage in the db
- * \param cal_partnum number of the calendar part
- */
-void cal_process_attachment(char *part_source, long msgnum, char *cal_partnum) {
-
- wprintf(_("<I>This message contains calendaring/scheduling information,"
- " but support for calendars is not available on this "
- "particular system. Please ask your system administrator to "
- "install a new version of the Citadel web service with "
- "calendaring enabled.</I><br />\n")
- );
-
-}
-
-/**
- * \brief say we can't display calendar items
- * \param msgnum number of the mesage in our db
- */
-void display_calendar(long msgnum) {
- wprintf(_("<i>"
- "Cannot display calendar item. You are seeing this error "
- "because your WebCit service has not been installed with "
- "calendar support. Please contact your system administrator."
- "</i><br />\n"));
-}
-
-/**
- * \brief say we can't display task items
- * \param msgnum number of the mesage in our db
- */
-void display_task(long msgnum) {
- wprintf(_("<i>"
- "Cannot display to-do item. You are seeing this error "
- "because your WebCit service has not been installed with "
- "calendar support. Please contact your system administrator."
- "</i><br />\n"));
-}
-/** ok, we have calendaring available */
-#else /* WEBCIT_WITH_CALENDAR_SERVICE */
-
-
-/****** End of handler stubs. Everything below this line is real. ******/
-
-
-
-
-/**
- * \brief Process a calendar object
- * ...at this point it's already been deserialized by cal_process_attachment()
- * \param cal teh calendar object
- * \param recursion_level call stack depth ??????
- * \param msgnum number of the mesage in our db
- * \param cal_partnum of the calendar object ????
- */
-void cal_process_object(icalcomponent *cal,
- int recursion_level,
- long msgnum,
- char *cal_partnum
-) {
- icalcomponent *c;
- icalproperty *method = NULL;
- icalproperty_method the_method = ICAL_METHOD_NONE;
- icalproperty *p;
- struct icaltimetype t;
- time_t tt;
- char buf[256];
- char conflict_name[256];
- char conflict_message[256];
- int is_update = 0;
-
- /** Leading HTML for the display of this object */
- if (recursion_level == 0) {
- wprintf("<CENTER><TABLE border=0>\n");
- }
-
- /** Look for a method */
- method = icalcomponent_get_first_property(cal, ICAL_METHOD_PROPERTY);
-
- /** See what we need to do with this */
- if (method != NULL) {
- the_method = icalproperty_get_method(method);
- switch(the_method) {
- case ICAL_METHOD_REQUEST:
- wprintf("<tr><td colspan=\"2\">\n"
- "<img align=\"center\" "
- "src=\"static/calarea_48x.gif\">"
- " "
- "<B>");
- wprintf(_("Meeting invitation"));
- wprintf("</B></TD></TR>\n");
- break;
- case ICAL_METHOD_REPLY:
- wprintf("<TR><TD COLSPAN=2>\n"
- "<IMG ALIGN=CENTER "
- "src=\"static/calarea_48x.gif\">"
- " "
- "<B>");
- wprintf(_("Attendee's reply to your invitation"));
- wprintf("</B></TD></TR>\n");
- break;
- case ICAL_METHOD_PUBLISH:
- wprintf("<TR><TD COLSPAN=2>\n"
- "<IMG ALIGN=CENTER "
- "src=\"static/calarea_48x.gif\">"
- " "
- "<B>");
- wprintf(_("Published event"));
- wprintf("</B></TD></TR>\n");
- break;
- default:
- wprintf("<TR><TD COLSPAN=2>");
- wprintf(_("This is an unknown type of calendar item."));
- wprintf("</TD></TR>\n");
- break;
- }
- }
-
- p = icalcomponent_get_first_property(cal, ICAL_SUMMARY_PROPERTY);
- if (p != NULL) {
- wprintf("<TR><TD><B>");
- wprintf(_("Summary:"));
- wprintf("</B></TD><TD>");
- escputs((char *)icalproperty_get_comment(p));
- wprintf("</TD></TR>\n");
- }
-
- p = icalcomponent_get_first_property(cal, ICAL_LOCATION_PROPERTY);
- if (p != NULL) {
- wprintf("<TR><TD><B>");
- wprintf(_("Location:"));
- wprintf("</B></TD><TD>");
- escputs((char *)icalproperty_get_comment(p));
- wprintf("</TD></TR>\n");
- }
-
- /**
- * Only show start/end times if we're actually looking at the VEVENT
- * component. Otherwise it shows bogus dates for things like timezone.
- */
- if (icalcomponent_isa(cal) == ICAL_VEVENT_COMPONENT) {
-
- p = icalcomponent_get_first_property(cal,
- ICAL_DTSTART_PROPERTY);
- if (p != NULL) {
- t = icalproperty_get_dtstart(p);
-
- if (t.is_date) {
- struct tm d_tm;
- char d_str[32];
- memset(&d_tm, 0, sizeof d_tm);
- d_tm.tm_year = t.year - 1900;
- d_tm.tm_mon = t.month - 1;
- d_tm.tm_mday = t.day;
- wc_strftime(d_str, sizeof d_str, "%x", &d_tm);
- wprintf("<TR><TD><B>");
- wprintf(_("Date:"));
- wprintf("</B></TD><TD>%s</TD></TR>", d_str);
- }
- else {
- tt = icaltime_as_timet(t);
- fmt_date(buf, tt, 0);
- wprintf("<TR><TD><B>");
- wprintf(_("Starting date/time:"));
- wprintf("</B></TD><TD>%s</TD></TR>", buf);
- }
- }
-
- p = icalcomponent_get_first_property(cal, ICAL_DTEND_PROPERTY);
- if (p != NULL) {
- t = icalproperty_get_dtend(p);
- tt = icaltime_as_timet(t);
- fmt_date(buf, tt, 0);
- wprintf("<TR><TD><B>");
- wprintf(_("Ending date/time:"));
- wprintf("</B></TD><TD>%s</TD></TR>", buf);
- }
-
- }
-
- p = icalcomponent_get_first_property(cal, ICAL_DESCRIPTION_PROPERTY);
- if (p != NULL) {
- wprintf("<TR><TD><B>");
- wprintf(_("Description:"));
- wprintf("</B></TD><TD>");
- escputs((char *)icalproperty_get_comment(p));
- wprintf("</TD></TR>\n");
- }
-
- /** 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)) {
- wprintf("<TR><TD><B>");
- wprintf(_("Attendee:"));
- wprintf("</B></TD><TD>");
- safestrncpy(buf, icalproperty_get_attendee(p), sizeof buf);
- if (!strncasecmp(buf, "MAILTO:", 7)) {
-
- /** screen name or email address */
- strcpy(buf, &buf[7]);
- striplt(buf);
- escputs(buf);
- wprintf(" ");
-
- /** participant status */
- partstat_as_string(buf, p);
- escputs(buf);
- }
- wprintf("</TD></TR>\n");
- }
-
- /** If the component has subcomponents, recurse through them. */
- for (c = icalcomponent_get_first_component(cal, ICAL_ANY_COMPONENT);
- (c != 0);
- c = icalcomponent_get_next_component(cal, ICAL_ANY_COMPONENT)) {
- /* Recursively process subcomponent */
- cal_process_object(c, recursion_level+1, msgnum, cal_partnum);
- }
-
- /** If this is a REQUEST, display conflicts and buttons */
- if (the_method == ICAL_METHOD_REQUEST) {
-
- /* Check for conflicts */
- lprintf(9, "Checking server calendar for conflicts...\n");
- serv_printf("ICAL conflicts|%ld|%s|", msgnum, cal_partnum);
- serv_getln(buf, sizeof buf);
- if (buf[0] == '1') {
- while (serv_getln(buf, sizeof buf), strcmp(buf, "000")) {
- extract_token(conflict_name, buf, 3, '|', sizeof conflict_name);
- is_update = extract_int(buf, 4);
-
- if (is_update) {
- snprintf(conflict_message, sizeof conflict_message,
- _("This is an update of '%s' which is already in your calendar."), conflict_name);
- }
- else {
- snprintf(conflict_message, sizeof conflict_message,
- _("This event would conflict with '%s' which is already in your calendar."), conflict_name);
- }
-
- wprintf("<TR><TD><B><I>%s</I></B></TD><td>",
- (is_update ?
- _("Update:") :
- _("CONFLICT:")
- )
- );
- escputs(conflict_message);
- wprintf("</TD></TR>\n");
- }
- }
- lprintf(9, "...done.\n");
-
- /** Display the Accept/Decline buttons */
- wprintf("<tr><td>%s</td>"
- "<td><font size=+1>"
- "<a href=\"respond_to_request?msgnum=%ld&cal_partnum=%s&sc=Accept\">%s</a>"
- " | "
- "<a href=\"respond_to_request?msgnum=%ld&cal_partnum=%s&sc=Tentative\">%s</a>"
- " | "
- "<a href=\"respond_to_request?msgnum=%ld&cal_partnum=%s&sc=Decline\">%s</a>"
- "</FONT></TD></TR>\n",
- _("How would you like to respond to this invitation?"),
- msgnum, cal_partnum, _("Accept"),
- msgnum, cal_partnum, _("Tentative"),
- msgnum, cal_partnum, _("Decline")
- );
-
- }
-
- /** If this is a REPLY, display update button */
- if (the_method == ICAL_METHOD_REPLY) {
-
- /** \todo In the future, if we want to validate this object before \
- * continuing, we can do it this way:
- serv_printf("ICAL whatever|%ld|%s|", msgnum, cal_partnum);
- serv_getln(buf, sizeof buf);
- }
- ***********/
-
- /** Display the update buttons */
- wprintf("<TR><TD>"
- "%s"
- "</td><td><font size=+1>"
- "<a href=\"handle_rsvp?msgnum=%ld&cal_partnum=%s&sc=Update\">%s</a>"
- " | "
- "<a href=\"handle_rsvp?msgnum=%ld&cal_partnum=%s&sc=Ignore\">%s</a>"
- "</font>"
- "</TD></TR>\n",
- _("Click <i>Update</i> to accept this reply and update your calendar."),
- msgnum, cal_partnum, _("Update"),
- msgnum, cal_partnum, _("Ignore")
- );
-
- }
-
- /** Trailing HTML for the display of this object */
- if (recursion_level == 0) {
-
- wprintf("</TR></TABLE></CENTER>\n");
- }
-}
-
-
-/**
- * \brief process calendar mail atachment
- * Deserialize a calendar object in a message so it can be processed.
- * (This is the main entry point for these things)
- * \param part_source the part of the message we want to parse
- * \param msgnum number of the mesage in our db
- * \param cal_partnum the number of the calendar item
- */
-void cal_process_attachment(char *part_source, long msgnum, char *cal_partnum) {
- icalcomponent *cal;
-
- cal = icalcomponent_new_from_string(part_source);
-
- if (cal == NULL) {
- wprintf(_("There was an error parsing this calendar item."));
- wprintf("<br />\n");
- return;
- }
-
- ical_dezonify(cal);
- cal_process_object(cal, 0, msgnum, cal_partnum);
-
- /* Free the memory we obtained from libical's constructor */
- icalcomponent_free(cal);
-}
-
-
-
-
-/**
- * \brief accept/decline meeting
- * Respond to a meeting request
- */
-void respond_to_request(void) {
- char buf[SIZ];
-
- output_headers(1, 1, 2, 0, 0, 0);
-
- wprintf("<div id=\"banner\">\n");
- wprintf("<TABLE WIDTH=100%% BORDER=0 BGCOLOR=\"#444455\"><TR><TD>"
- "<SPAN CLASS=\"titlebar\">");
- wprintf(_("Respond to meeting request"));
- wprintf("</SPAN>"
- "</TD></TR></TABLE>\n"
- );
- wprintf("</div>\n<div id=\"content\">\n");
-
- serv_printf("ICAL respond|%s|%s|%s|",
- bstr("msgnum"),
- bstr("cal_partnum"),
- bstr("sc")
- );
- serv_getln(buf, sizeof buf);
-
- if (buf[0] == '2') {
- wprintf("<TABLE BORDER=0><TR><TD>"
- "<img src=\"static/calarea_48x.gif\" ALIGN=CENTER>"
- "</TD><TD>"
- );
- if (!strcasecmp(bstr("sc"), "accept")) {
- wprintf(_("You have accepted this meeting invitation. "
- "It has been entered into your calendar.")
- );
- } else if (!strcasecmp(bstr("sc"), "tentative")) {
- wprintf(_("You have tentatively accepted this meeting invitation. "
- "It has been 'pencilled in' to your calendar.")
- );
- } else if (!strcasecmp(bstr("sc"), "decline")) {
- wprintf(_("You have declined this meeting invitation. "
- "It has <b>not</b> been entered into your calendar.")
- );
- }
- wprintf(" ");
- wprintf(_("A reply has been sent to the meeting organizer."));
- wprintf("</TD></TR></TABLE>\n");
- } else {
- wprintf("<img src=\"static/error.gif\" ALIGN=CENTER>"
- "%s\n", &buf[4]);
- }
-
- wprintf("<a href=\"dotskip?room=");
- urlescputs(WC->wc_roomname);
- wprintf("\"><br />");
- wprintf(_("Return to messages"));
- wprintf("</A><br />\n");
-
- wDumpContent(1);
-}
-
-
-
-/**
- * \brief Handle an incoming RSVP
- */
-void handle_rsvp(void) {
- char buf[SIZ];
-
- output_headers(1, 1, 2, 0, 0, 0);
-
- wprintf("<div id=\"banner\">\n");
- wprintf("<TABLE WIDTH=100%% BORDER=0 BGCOLOR=\"#444455\"><TR><TD>"
- "<SPAN CLASS=\"titlebar\">");
- wprintf(_("Update your calendar with this RSVP"));
- wprintf("</SPAN>"
- "</TD></TR></TABLE>\n"
- "</div>\n<div id=\"content\">\n"
- );
-
- serv_printf("ICAL handle_rsvp|%s|%s|%s|",
- bstr("msgnum"),
- bstr("cal_partnum"),
- bstr("sc")
- );
- serv_getln(buf, sizeof buf);
-
- if (buf[0] == '2') {
- wprintf("<TABLE BORDER=0><TR><TD>"
- "<img src=\"static/calarea_48x.gif\" ALIGN=CENTER>"
- "</TD><TD>"
- );
- if (!strcasecmp(bstr("sc"), "update")) {
- wprintf(_("Your calendar has been updated to reflect this RSVP."));
- } else if (!strcasecmp(bstr("sc"), "ignore")) {
- wprintf(_("You have chosen to ignore this RSVP. "
- "Your calendar has <b>not</b> been updated.")
- );
- }
- wprintf("</TD></TR></TABLE>\n"
- );
- } else {
- wprintf("<img src=\"static/error.gif\" ALIGN=CENTER>"
- "%s\n", &buf[4]);
- }
-
- wprintf("<a href=\"dotskip?room=");
- urlescputs(WC->wc_roomname);
- wprintf("\"><br />");
- wprintf(_("Return to messages"));
- wprintf("</A><br />\n");
-
- wDumpContent(1);
-}
-
-
-
-/*@}*/
-/*-----------------------------------------------------------------------**/
-
-
-
-/**
- * \defgroup MsgDisplayHandlers Display handlers for message reading
- * \ingroup Calendaring
- */
-
-/*@{*/
-
-
-
-/**
- * \brief get items, keep them.
- * If we're reading calendar items, just store them for now. We have to
- * sort and re-output them later when we draw the calendar.
- * \param cal Our calendar to process
- * \param msgnum number of the mesage in our db
- */
-void display_individual_cal(icalcomponent *cal, long msgnum) {
-
- WC->num_cal += 1;
-
- WC->disp_cal = realloc(WC->disp_cal,
- (sizeof(struct disp_cal) * WC->num_cal) );
- WC->disp_cal[WC->num_cal - 1].cal = icalcomponent_new_clone(cal);
-
- WC->disp_cal[WC->num_cal - 1].cal_msgnum = msgnum;
-}
-
-
-
-/*
- * \brief edit a task
- * Display a task by itself (for editing)
- * \param supplied_vtodo the todo item we want to edit
- * \param msgnum number of the mesage in our db
- */
-void display_edit_individual_task(icalcomponent *supplied_vtodo, long msgnum) {
- icalcomponent *vtodo;
- icalproperty *p;
- struct icaltimetype t;
- time_t now;
- int created_new_vtodo = 0;
-
- now = time(NULL);
-
- if (supplied_vtodo != NULL) {
- vtodo = supplied_vtodo;
-
- /**
- * If we're looking at a fully encapsulated VCALENDAR
- * rather than a VTODO component, attempt to use the first
- * relevant VTODO subcomponent. If there is none, the
- * NULL returned by icalcomponent_get_first_component() will
- * tell the next iteration of this function to create a
- * new one.
- */
- if (icalcomponent_isa(vtodo) == ICAL_VCALENDAR_COMPONENT) {
- display_edit_individual_task(
- icalcomponent_get_first_component(
- vtodo, ICAL_VTODO_COMPONENT
- ), msgnum
- );
- return;
- }
- }
- else {
- vtodo = icalcomponent_new(ICAL_VTODO_COMPONENT);
- created_new_vtodo = 1;
- }
-
- output_headers(1, 1, 2, 0, 0, 0);
- wprintf("<div id=\"banner\">\n"
- "<TABLE WIDTH=100%% BORDER=0 BGCOLOR=\"#444455\"><TR>"
- "<TD><img src=\"static/taskmanag_48x.gif\"></TD>"
- "<td><SPAN CLASS=\"titlebar\">");
- wprintf(_("Edit task"));
- wprintf("</SPAN>"
- "</TD></TR></TABLE>\n"
- "</div>\n<div id=\"content\">\n"
- );
-
- wprintf("<div class=\"fix_scrollbar_bug\">"
- "<table border=0 width=100%% bgcolor=\"#ffffff\"><tr><td>");
-
- wprintf("<FORM METHOD=\"POST\" action=\"save_task\">\n");
- wprintf("<INPUT TYPE=\"hidden\" NAME=\"msgnum\" VALUE=\"%ld\">\n",
- msgnum);
-
- wprintf("<TABLE border=0>\n");
-
- wprintf("<TR><TD>");
- wprintf(_("Summary:"));
- wprintf("</TD><TD>"
- "<INPUT TYPE=\"text\" NAME=\"summary\" "
- "MAXLENGTH=\"64\" SIZE=\"64\" VALUE=\"");
- p = icalcomponent_get_first_property(vtodo, ICAL_SUMMARY_PROPERTY);
- if (p != NULL) {
- escputs((char *)icalproperty_get_comment(p));
- }
- wprintf("\"></TD></TR>\n");
-
- wprintf("<TR><TD>");
- wprintf(_("Start date:"));
- wprintf("</TD><TD>");
- p = icalcomponent_get_first_property(vtodo, ICAL_DTSTART_PROPERTY);
- if (p != NULL) {
- t = icalproperty_get_dtstart(p);
- }
- else {
- t = icaltime_from_timet(now, 0);
- }
- display_icaltimetype_as_webform(&t, "dtstart");
- wprintf("</TD></TR>\n");
-
- wprintf("<TR><TD>");
- wprintf(_("Due date:"));
- wprintf("</TD><TD>");
- p = icalcomponent_get_first_property(vtodo, ICAL_DUE_PROPERTY);
- if (p != NULL) {
- t = icalproperty_get_due(p);
- }
- else {
- t = icaltime_from_timet(now, 0);
- }
- display_icaltimetype_as_webform(&t, "due");
- wprintf("</TD></TR>\n");
- wprintf("<TR><TD>");
- wprintf(_("Description:"));
- wprintf("</TD><TD>");
- wprintf("<TEXTAREA NAME=\"description\" wrap=soft "
- "ROWS=10 COLS=80 WIDTH=80>\n"
- );
- p = icalcomponent_get_first_property(vtodo, ICAL_DESCRIPTION_PROPERTY);
- if (p != NULL) {
- escputs((char *)icalproperty_get_comment(p));
- }
- wprintf("</TEXTAREA></TD></TR></TABLE>\n");
-
- wprintf("<CENTER>"
- "<INPUT TYPE=\"submit\" NAME=\"save_button\" VALUE=\"%s\">"
- " "
- "<INPUT TYPE=\"submit\" NAME=\"delete_button\" VALUE=\"%s\">\n"
- " "
- "<INPUT TYPE=\"submit\" NAME=\"cancel_button\" VALUE=\"%s\">\n"
- "</CENTER>\n",
- _("Save"),
- _("Delete"),
- _("Cancel")
- );
-
- wprintf("</FORM>\n");
-
- wprintf("</td></tr></table></div>\n");
- wDumpContent(1);
-
- if (created_new_vtodo) {
- icalcomponent_free(vtodo);
- }
-}
-
-/*
- * \brief Save an edited task
- * \param supplied_vtodo the task to save
- * \param msgnum number of the mesage in our db
- */
-void save_individual_task(icalcomponent *supplied_vtodo, long msgnum) {
- char buf[SIZ];
- int delete_existing = 0;
- icalproperty *prop;
- icalcomponent *vtodo, *encaps;
- int created_new_vtodo = 0;
- int i;
- int sequence = 0;
- struct icaltimetype t;
-
- if (supplied_vtodo != NULL) {
- vtodo = supplied_vtodo;
- /**
- * If we're looking at a fully encapsulated VCALENDAR
- * rather than a VTODO component, attempt to use the first
- * relevant VTODO subcomponent. If there is none, the
- * NULL returned by icalcomponent_get_first_component() will
- * tell the next iteration of this function to create a
- * new one.
- */
- if (icalcomponent_isa(vtodo) == ICAL_VCALENDAR_COMPONENT) {
- save_individual_task(
- icalcomponent_get_first_component(
- vtodo, ICAL_VTODO_COMPONENT
- ), msgnum
- );
- return;
- }
- }
- else {
- vtodo = icalcomponent_new(ICAL_VTODO_COMPONENT);
- created_new_vtodo = 1;
- }
-
- if (strlen(bstr("save_button")) > 0) {
-
- /** Replace values in the component with ones from the form */
-
- while (prop = icalcomponent_get_first_property(vtodo,
- ICAL_SUMMARY_PROPERTY), prop != NULL) {
- icalcomponent_remove_property(vtodo, prop);
- icalproperty_free(prop);
- }
- icalcomponent_add_property(vtodo,
- icalproperty_new_summary(bstr("summary")));
-
- while (prop = icalcomponent_get_first_property(vtodo,
- ICAL_DESCRIPTION_PROPERTY), prop != NULL) {
- icalcomponent_remove_property(vtodo, prop);
- icalproperty_free(prop);
- }
- icalcomponent_add_property(vtodo,
- icalproperty_new_description(bstr("description")));
-
- while (prop = icalcomponent_get_first_property(vtodo,
- ICAL_DTSTART_PROPERTY), prop != NULL) {
- icalcomponent_remove_property(vtodo, prop);
- icalproperty_free(prop);
- }
- icaltime_from_webform(&t, "dtstart");
- icalcomponent_add_property(vtodo,
- icalproperty_new_dtstart(t)
- );
-
- while (prop = icalcomponent_get_first_property(vtodo,
- ICAL_DUE_PROPERTY), prop != NULL) {
- icalcomponent_remove_property(vtodo, prop);
- icalproperty_free(prop);
- }
- icaltime_from_webform(&t, "due");
- icalcomponent_add_property(vtodo,
- icalproperty_new_due(t)
- );
-
- /** Give this task a UID if it doesn't have one. */
- lprintf(9, "Give this task a UID if it doesn't have one.\n");
- if (icalcomponent_get_first_property(vtodo,
- ICAL_UID_PROPERTY) == NULL) {
- generate_uuid(buf);
- icalcomponent_add_property(vtodo,
- icalproperty_new_uid(buf)
- );
- }
-
- /** Increment the sequence ID */
- lprintf(9, "Increment the sequence ID\n");
- while (prop = icalcomponent_get_first_property(vtodo,
- ICAL_SEQUENCE_PROPERTY), (prop != NULL) ) {
- i = icalproperty_get_sequence(prop);
- lprintf(9, "Sequence was %d\n", i);
- if (i > sequence) sequence = i;
- icalcomponent_remove_property(vtodo, prop);
- icalproperty_free(prop);
- }
- ++sequence;
- lprintf(9, "New sequence is %d. Adding...\n", sequence);
- icalcomponent_add_property(vtodo,
- icalproperty_new_sequence(sequence)
- );
-
- /**
- * Encapsulate event into full VCALENDAR component. Clone it first,
- * for two reasons: one, it's easier to just free the whole thing
- * when we're done instead of unbundling, but more importantly, we
- * can't encapsulate something that may already be encapsulated
- * somewhere else.
- */
- lprintf(9, "Encapsulating into full VCALENDAR component\n");
- encaps = ical_encapsulate_subcomponent(icalcomponent_new_clone(vtodo));
-
- /* Serialize it and save it to the message base */
- serv_puts("ENT0 1|||4");
- serv_getln(buf, sizeof buf);
- if (buf[0] == '4') {
- serv_puts("Content-type: text/calendar");
- serv_puts("");
- serv_puts(icalcomponent_as_ical_string(encaps));
- serv_puts("000");
-
- /**
- * Probably not necessary; the server will see the UID
- * of the object and delete the old one anyway, but
- * just in case...
- */
- delete_existing = 1;
- }
- icalcomponent_free(encaps);
- }
-
- /**
- * If the user clicked 'Delete' then explicitly delete the message.
- */
- if (strlen(bstr("delete_button")) > 0) {
- delete_existing = 1;
- }
-
- if ( (delete_existing) && (msgnum > 0L) ) {
- serv_printf("DELE %ld", atol(bstr("msgnum")));
- serv_getln(buf, sizeof buf);
- }
-
- if (created_new_vtodo) {
- icalcomponent_free(vtodo);
- }
-
- /** Go back to the task list */
- readloop("readfwd");
-}
-
-
-
-/**
- * \brief generic item handler
- * Code common to all display handlers. Given a message number and a MIME
- * type, we load the message and hunt for that MIME type. If found, we load
- * the relevant part, deserialize it into a libical component, filter it for
- * the requested object type, and feed it to the specified handler.
- * \param mimetype mimetyp of our object
- * \param which_kind sort of ical type
- * \param msgnum number of the mesage in our db
- * \param callback a funcion \todo
- *
- */
-void display_using_handler(long msgnum,
- char *mimetype,
- icalcomponent_kind which_kind,
- void (*callback)(icalcomponent *, long)
- ) {
- char buf[SIZ];
- char mime_partnum[SIZ];
- char mime_filename[SIZ];
- char mime_content_type[SIZ];
- char mime_disposition[SIZ];
- int mime_length;
- char relevant_partnum[SIZ];
- char *relevant_source = NULL;
- icalcomponent *cal, *c;
-
- sprintf(buf, "MSG0 %ld|1", msgnum); /* ask for headers only */
- serv_puts(buf);
- serv_getln(buf, sizeof buf);
- if (buf[0] != '1') return;
-
- while (serv_getln(buf, sizeof buf), strcmp(buf, "000")) {
- if (!strncasecmp(buf, "part=", 5)) {
- extract_token(mime_filename, &buf[5], 1, '|', sizeof mime_filename);
- extract_token(mime_partnum, &buf[5], 2, '|', sizeof mime_partnum);
- extract_token(mime_disposition, &buf[5], 3, '|', sizeof mime_disposition);
- extract_token(mime_content_type, &buf[5], 4, '|', sizeof mime_content_type);
- mime_length = extract_int(&buf[5], 5);
-
- if (!strcasecmp(mime_content_type, "text/calendar")) {
- strcpy(relevant_partnum, mime_partnum);
- }
-
- }
- }
-
- if (strlen(relevant_partnum) > 0) {
- relevant_source = load_mimepart(msgnum, relevant_partnum);
- if (relevant_source != NULL) {
-
- cal = icalcomponent_new_from_string(relevant_source);
- if (cal != NULL) {
-
- ical_dezonify(cal);
-
- /** Simple components of desired type */
- if (icalcomponent_isa(cal) == which_kind) {
- callback(cal, msgnum);
- }
-
- /** Subcomponents of desired type */
- for (c = icalcomponent_get_first_component(cal,
- which_kind);
- (c != 0);
- c = icalcomponent_get_next_component(cal,
- which_kind)) {
- callback(c, msgnum);
- }
- icalcomponent_free(cal);
- }
- free(relevant_source);
- }
- }
-
-}
-
-/**
- * \brief display whole calendar
- * \param msgnum number of the mesage in our db
- */
-void display_calendar(long msgnum) {
- display_using_handler(msgnum, "text/calendar",
- ICAL_VEVENT_COMPONENT,
- display_individual_cal);
-}
-
-/**
- * \brief display whole taksview
- * \param msgnum number of the mesage in our db
- */
-void display_task(long msgnum) {
- display_using_handler(msgnum, "text/calendar",
- ICAL_VTODO_COMPONENT,
- display_individual_cal);
-}
-
-/**
- * \brief display the editor component for a task
- */
-void display_edit_task(void) {
- long msgnum = 0L;
-
- /** Force change the room if we have to */
- if (strlen(bstr("taskrm")) > 0) {
- gotoroom(bstr("taskrm"));
- }
-
- msgnum = atol(bstr("msgnum"));
- if (msgnum > 0L) {
- /** existing task */
- display_using_handler(msgnum, "text/calendar",
- ICAL_VTODO_COMPONENT,
- display_edit_individual_task);
- }
- else {
- /** new task */
- display_edit_individual_task(NULL, 0L);
- }
-}
-
-/**
- *\brief save an edited task
- */
-void save_task(void) {
- long msgnum = 0L;
-
- msgnum = atol(bstr("msgnum"));
- if (msgnum > 0L) {
- display_using_handler(msgnum, "text/calendar",
- ICAL_VTODO_COMPONENT,
- save_individual_task);
- }
- else {
- save_individual_task(NULL, 0L);
- }
-}
-
-/**
- * \brief display the editor component for an event
- */
-void display_edit_event(void) {
- long msgnum = 0L;
-
- msgnum = atol(bstr("msgnum"));
- if (msgnum > 0L) {
- /* existing event */
- display_using_handler(msgnum, "text/calendar",
- ICAL_VEVENT_COMPONENT,
- display_edit_individual_event);
- }
- else {
- /* new event */
- display_edit_individual_event(NULL, 0L);
- }
-}
-
-/**
- * \brief save an edited event
- */
-void save_event(void) {
- long msgnum = 0L;
-
- msgnum = atol(bstr("msgnum"));
-
- if (msgnum > 0L) {
- display_using_handler(msgnum, "text/calendar",
- ICAL_VEVENT_COMPONENT,
- save_individual_event);
- }
- else {
- save_individual_event(NULL, 0L);
- }
-}
-
-
-
-
-
-/**
- * \brief freebusy display (for client software)
- * \param req dunno. ?????
- */
-void do_freebusy(char *req) {
- char who[SIZ];
- char buf[SIZ];
- char *fb;
-
- extract_token(who, req, 1, ' ', sizeof who);
- if (!strncasecmp(who, "/freebusy/", 10)) {
- strcpy(who, &who[10]);
- }
- unescape_input(who);
-
- if ( (!strcasecmp(&who[strlen(who)-4], ".vcf"))
- || (!strcasecmp(&who[strlen(who)-4], ".ifb"))
- || (!strcasecmp(&who[strlen(who)-4], ".vfb")) ) {
- who[strlen(who)-4] = 0;
- }
-
- lprintf(9, "freebusy requested for <%s>\n", who);
- serv_printf("ICAL freebusy|%s", who);
- serv_getln(buf, sizeof buf);
-
- if (buf[0] != '1') {
- wprintf("HTTP/1.1 404 %s\n", &buf[4]);
- output_headers(0, 0, 0, 0, 0, 0);
- wprintf("Content-Type: text/plain\r\n");
- wprintf("\r\n");
- wprintf("%s\n", &buf[4]);
- return;
- }
-
- fb = read_server_text();
- http_transmit_thing(fb, strlen(fb), "text/calendar", 0);
- free(fb);
-}
-
-
-
-#endif /* WEBCIT_WITH_CALENDAR_SERVICE */
-
-
-/*@}*/
+++ /dev/null
-/*
- * $Id$
- */
-/**
- * \defgroup MiscCal Miscellaneous functions which handle calendar components.
- * \ingroup Calendaring
- */
-/*@{*/
-#include "webcit.h"
-#include "webserver.h"
-
-/** Hour strings */
-char *hourname[] = {
- "12am", "1am", "2am", "3am", "4am", "5am", "6am",
- "7am", "8am", "9am", "10am", "11am", "12pm",
- "1pm", "2pm", "3pm", "4pm", "5pm", "6pm",
- "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
- * fields for editing the date and time. When the user submits the form, the
- * results can be fed back into the second function, which turns it back into
- * an icaltimetype. The "prefix" string required by both functions is prepended
- * to all field names. This allows a form to contain more than one date/time
- * 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
- * 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) {
- 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;
- time_t monthselect_time;
- struct tm monthselect_tm;
- char monthselect_str[32];
- char calhourformat[16];
-
- get_preference("calhourformat", calhourformat, sizeof calhourformat);
-
- 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;
- tt = icaltime_as_timet(*t);
- if (all_day_event) {
- gmtime_r(&tt, &tm);
- }
- else {
- localtime_r(&tt, &tm);
- }
-
- wprintf(_("Month: "));
- wprintf("<SELECT NAME=\"%s_month\" SIZE=\"1\">\n", prefix);
- for (i=0; i<=11; ++i) {
- monthselect_time = 1137997451 + (i * 2592000);
- localtime_r(&monthselect_time, &monthselect_tm);
- wc_strftime(monthselect_str, sizeof monthselect_str, "%B", &monthselect_tm);
- wprintf("<OPTION %s VALUE=\"%d\">%s</OPTION>\n",
- ((tm.tm_mon == i) ? "SELECTED" : ""),
- i+1,
- monthselect_str
- );
- }
- wprintf("</SELECT>\n");
-
- wprintf(_("Day: "));
- wprintf("<SELECT NAME=\"%s_day\" SIZE=\"1\">\n", prefix);
- for (i=1; i<=31; ++i) {
- wprintf("<OPTION %s VALUE=\"%d\">%d</OPTION>\n",
- ((tm.tm_mday == i) ? "SELECTED" : ""),
- i, i
- );
- }
- wprintf("</SELECT>\n");
-
- wprintf(_("Year: "));
- wprintf("<SELECT NAME=\"%s_year\" SIZE=\"1\">\n", prefix);
- if ((this_year - t->year) > span) {
- wprintf("<OPTION SELECTED VALUE=\"%d\">%d</OPTION>\n",
- t->year, t->year);
- }
- for (i=(this_year-span); i<=(this_year+span); ++i) {
- wprintf("<OPTION %s VALUE=\"%d\">%d</OPTION>\n",
- ((t->year == i) ? "SELECTED" : ""),
- i, i
- );
- }
- if ((t->year - this_year) > span) {
- wprintf("<OPTION SELECTED VALUE=\"%d\">%d</OPTION>\n",
- t->year, t->year);
- }
- wprintf("</SELECT>\n");
-
- wprintf(_("Hour: "));
- wprintf("<SELECT NAME=\"%s_hour\" SIZE=\"1\">\n", prefix);
- for (i=0; i<=23; ++i) {
-
- if (!strcasecmp(calhourformat, "24")) {
- wprintf("<OPTION %s VALUE=\"%d\">%d</OPTION>\n",
- ((tm.tm_hour == i) ? "SELECTED" : ""),
- i, i
- );
- }
- else {
- wprintf("<OPTION %s VALUE=\"%d\">%s</OPTION>\n",
- ((tm.tm_hour == i) ? "SELECTED" : ""),
- i, hourname[i]
- );
- }
-
- }
- wprintf("</SELECT>\n");
-
- wprintf(_("Minute: "));
- wprintf("<SELECT NAME=\"%s_minute\" SIZE=\"1\">\n", prefix);
- for (i=0; i<=59; ++i) {
- if ( (i % 5 == 0) || (tm.tm_min == i) ) {
- wprintf("<OPTION %s VALUE=\"%d\">:%02d</OPTION>\n",
- ((tm.tm_min == i) ? "SELECTED" : ""),
- i, i
- );
- }
- }
- wprintf("</SELECT>\n");
-}
-
-/**
- *\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 ????
- */
-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));
-}
-
-/**
- *\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 ????
- */
-
-void icaltime_from_webform_dateonly(struct icaltimetype *t, char *prefix) {
- char vname[32];
-
- 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;
- 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;
- icalparameter_partstat partstat;
-
- strcpy(buf, _("(status unknown)"));
-
- partstat_param = icalproperty_get_first_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;
- }
-}
-
-
-/**
- * \brief embedd
- * Utility function to encapsulate a subcomponent into a full VCALENDAR
- * \param subcomp the component to encapsulate
- * \returns the meta object ???
- */
-icalcomponent *ical_encapsulate_subcomponent(icalcomponent *subcomp) {
- icalcomponent *encaps;
-
- /* lprintf(9, "ical_encapsulate_subcomponent() called\n"); */
-
- if (subcomp == NULL) {
- lprintf(3, "ERROR: called with NULL argument!\n");
- return NULL;
- }
-
- /**
- * If we're already looking at a full VCALENDAR component,
- * don't bother ... just return itself.
- */
- if (icalcomponent_isa(subcomp) == ICAL_VCALENDAR_COMPONENT) {
- return subcomp;
- }
-
- /** 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__);
- return NULL;
- }
-
- /** Set the Product ID */
- icalcomponent_add_property(encaps, icalproperty_new_prodid(PRODID));
-
- /** 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);
-
- /** Convert all timestamps to UTC so we don't have to deal with
- * stupid VTIMEZONE crap.
- */
- ical_dezonify(encaps);
-
- /** Return the object we just created. */
- return(encaps);
-}
-
-
-
-
-#endif
-/*@}*/
+++ /dev/null
-/*
- * $Id$
- */
-/**
- * \defgroup CalHtmlHandles Handles the HTML display of calendar items.
- * \ingroup Calendaring
- */
-/*@{*/
-#include "webcit.h"
-#include "webserver.h"
-
-#ifndef WEBCIT_WITH_CALENDAR_SERVICE
-
-/**\brief stub for non-libical builds */
-void do_calendar_view(void) {
- wprintf("<center><i>");
- wprintf(_("The calendar view is not available."));
- wprintf("</i></center><br />\n");
-}
-
-/**\brief stub for non-libical builds */
-void do_tasks_view(void) {
- wprintf("<center><I>");
- wprintf(_("The tasks view is not available."));
- wprintf("</i></center><br />\n");
-}
-
-#else /* WEBCIT_WITH_CALENDAR_SERVICE */
-
-/****************************************************************************/
-
-/**
- * \brief Display one day of a whole month view of a calendar
- * \param thetime the month we want to see
- */
-void calendar_month_view_display_events(time_t thetime) {
- int i;
- time_t event_tt;
- struct tm event_tm;
- struct tm today_tm;
- icalproperty *p;
- struct icaltimetype t;
- int month, day, year;
- int all_day_event = 0;
-
- if (WC->num_cal == 0) {
- wprintf("<br /><br /><br />\n");
- return;
- }
-
- localtime_r(&thetime, &today_tm);
- month = today_tm.tm_mon + 1;
- day = today_tm.tm_mday;
- year = today_tm.tm_year + 1900;
-
- for (i=0; i<(WC->num_cal); ++i) {
- p = icalcomponent_get_first_property(WC->disp_cal[i].cal,
- ICAL_DTSTART_PROPERTY);
- if (p != NULL) {
- t = icalproperty_get_dtstart(p);
- event_tt = icaltime_as_timet(t);
-
- if (t.is_date) all_day_event = 1;
- else all_day_event = 0;
-
- if (all_day_event) {
- gmtime_r(&event_tt, &event_tm);
- }
- else {
- localtime_r(&event_tt, &event_tm);
- }
-
- if ((event_tm.tm_year == today_tm.tm_year)
- && (event_tm.tm_mon == today_tm.tm_mon)
- && (event_tm.tm_mday == today_tm.tm_mday)) {
-
- p = icalcomponent_get_first_property(
- WC->disp_cal[i].cal,
- ICAL_SUMMARY_PROPERTY);
- if (p != NULL) {
-
- if (all_day_event) {
- wprintf("<table border=0 cellpadding=2><TR>"
- "<td bgcolor=\"#CCCCDD\">"
- );
- }
-
- wprintf("<font size=-1>"
- "<a href=\"display_edit_event?msgnum=%ld&calview=%s&year=%s&month=%s&day=%s\">",
- WC->disp_cal[i].cal_msgnum,
- bstr("calview"),
- bstr("year"),
- bstr("month"),
- bstr("day")
- );
- escputs((char *)
- icalproperty_get_comment(p));
- wprintf("</a></font><br />\n");
-
- if (all_day_event) {
- wprintf("</td></tr></table>");
- }
-
- }
-
- }
-
-
- }
- }
-}
-
-
-/**
- * \brief Display one day of a whole month view of a calendar
- * \param thetime the month we want to see
- */
-void calendar_month_view_brief_events(time_t thetime, const char *daycolor) {
- int i;
- time_t event_tt;
- time_t event_tts;
- time_t event_tte;
- struct tm event_tms;
- struct tm event_tme;
- struct tm today_tm;
- icalproperty *p;
- icalproperty *e;
- struct icaltimetype t;
- int month, day, year;
- int all_day_event = 0;
- char calhourformat[16];
- char *timeformat;
-
- get_preference("calhourformat", calhourformat, sizeof calhourformat);
- if (!strcasecmp(calhourformat, "24")) timeformat="%k:%M";
- else timeformat="%I:%M %p";
-
- localtime_r(&thetime, &today_tm);
- month = today_tm.tm_mon + 1;
- day = today_tm.tm_mday;
- year = today_tm.tm_year + 1900;
-
- for (i=0; i<(WC->num_cal); ++i) {
- p = icalcomponent_get_first_property(WC->disp_cal[i].cal,
- ICAL_DTSTART_PROPERTY);
- if (p != NULL) {
- t = icalproperty_get_dtstart(p);
- event_tt = icaltime_as_timet(t);
- event_tts=event_tt;
- if (t.is_date) all_day_event = 1;
- else all_day_event = 0;
-
- if (all_day_event) {
- gmtime_r(&event_tts, &event_tms);
- }
- else {
- localtime_r(&event_tts, &event_tms);
- }
- /** \todo epoch &! daymask */
- if ((event_tms.tm_year == today_tm.tm_year)
- && (event_tms.tm_mon == today_tm.tm_mon)
- && (event_tms.tm_mday == today_tm.tm_mday)) {
-
-
- char sbuf[255];
- char ebuf[255];
-
- p = icalcomponent_get_first_property(
- WC->disp_cal[i].cal,
- ICAL_SUMMARY_PROPERTY);
- e = icalcomponent_get_first_property(
- WC->disp_cal[i].cal,
- ICAL_DTEND_PROPERTY);
- if ((p != NULL) && (e != NULL)) {
- time_t difftime;
- int hours, minutes;
- t = icalproperty_get_dtend(e);
- event_tte = icaltime_as_timet(t);
- localtime_r(&event_tte, &event_tme);
- difftime=(event_tte-event_tts)/60;
- hours=(int)(difftime / 60);
- minutes=difftime % 60;
- wprintf("<tr><td bgcolor='%s'>%i:%2i</td><td bgcolor='%s'>"
- "<font size=-1>"
- "<a href=\"display_edit_event?msgnum=%ld&calview=%s&year=%s&month=%s&day=%s\">",
- daycolor,
- hours, minutes,
- daycolor,
- WC->disp_cal[i].cal_msgnum,
- bstr("calview"),
- bstr("year"),
- bstr("month"),
- bstr("day")
- );
-
- escputs((char *)
- icalproperty_get_comment(p));
- /** \todo: allso ammitime format */
- wc_strftime(&sbuf[0], sizeof(sbuf), timeformat, &event_tms);
- wc_strftime(&ebuf[0], sizeof(sbuf), timeformat, &event_tme);
-
- wprintf("</a></font></td>"
- "<td bgcolor='%s'>%s</td><td bgcolor='%s'>%s</td></tr>",
- daycolor,
- sbuf,
- daycolor,
- ebuf);
-
- }
-
- }
-
-
- }
- }
-}
-
-
-/**
- * \brief view one month. pretty view
- * \param year the year
- * \param month the month
- * \param day the actual day we want to see
- */
-void calendar_month_view(int year, int month, int day) {
- struct tm starting_tm;
- struct tm tm;
- time_t thetime;
- int i;
- time_t previous_month;
- time_t next_month;
- time_t colheader_time;
- struct tm colheader_tm;
- char colheader_label[32];
-
- /** Determine what day to start.
- * First, back up to the 1st of the month...
- */
- memset(&starting_tm, 0, sizeof(struct tm));
- starting_tm.tm_year = year - 1900;
- starting_tm.tm_mon = month - 1;
- starting_tm.tm_mday = day;
- thetime = mktime(&starting_tm);
-
- memcpy(&tm, &starting_tm, sizeof(struct tm));
- while (tm.tm_mday != 1) {
- thetime = thetime - (time_t)86400; /* go back 24 hours */
- localtime_r(&thetime, &tm);
- }
-
- /** Determine previous and next months ... for links */
- previous_month = thetime - (time_t)864000L; /* back 10 days */
- next_month = thetime + (time_t)(31L * 86400L); /* ahead 31 days */
-
- /** Now back up until we're on a Sunday */
- localtime_r(&thetime, &tm);
- while (tm.tm_wday != 0) {
- thetime = thetime - (time_t)86400; /* go back 24 hours */
- localtime_r(&thetime, &tm);
- }
-
- /** Outer table (to get the background color) */
- wprintf("<div class=\"fix_scrollbar_bug\">"
- "<table width=100%% border=0 cellpadding=0 cellspacing=0 "
- "bgcolor=#204B78><TR><TD>\n");
-
- wprintf("<table width=100%% border=0 cellpadding=0 cellspacing=0><tr>\n");
-
- wprintf("<td align=center>");
-
- localtime_r(&previous_month, &tm);
- wprintf("<a href=\"readfwd?calview=month&year=%d&month=%d&day=1\">",
- (int)(tm.tm_year)+1900, tm.tm_mon + 1);
- wprintf("<img align=middle src=\"static/prevdate_32x.gif\" border=0></A>\n");
-
- wc_strftime(colheader_label, sizeof colheader_label, "%B", &starting_tm);
- wprintf(" "
- "<font size=+1 color=\"#FFFFFF\">"
- "%s %d"
- "</font>"
- " ", colheader_label, year);
-
- localtime_r(&next_month, &tm);
- wprintf("<a href=\"readfwd?calview=month&year=%d&month=%d&day=1\">",
- (int)(tm.tm_year)+1900, tm.tm_mon + 1);
- wprintf("<img align=middle src=\"static/nextdate_32x.gif\" border=0></A>\n");
-
- wprintf("</td></tr></table>\n");
-
- /** Inner table (the real one) */
- wprintf("<table width=100%% border=0 cellpadding=1 cellspacing=1 "
- "bgcolor=#204B78><tr>");
- colheader_time = thetime;
- for (i=0; i<7; ++i) {
- colheader_time = thetime + (i * 86400) ;
- localtime_r(&colheader_time, &colheader_tm);
- wc_strftime(colheader_label, sizeof colheader_label, "%A", &colheader_tm);
- wprintf("<td align=center width=14%%>"
- "<font color=\"#FFFFFF\">%s</font></th>", colheader_label);
-
- }
- wprintf("</tr>\n");
-
- /** Now do 35 days */
- for (i = 0; i < 35; ++i) {
- localtime_r(&thetime, &tm);
-
- /** Before displaying Sunday, start a new row */
- if ((i % 7) == 0) {
- wprintf("<tr>");
- }
-
- wprintf("<td bgcolor=\"#%s\" width=14%% height=60 align=left valign=top><b>",
- ((tm.tm_mon != month-1) ? "DDDDDD" :
- ((tm.tm_wday==0 || tm.tm_wday==6) ? "EEEECC" :
- "FFFFFF"))
- );
- if ((i==0) || (tm.tm_mday == 1)) {
- wc_strftime(colheader_label, sizeof colheader_label, "%B", &tm);
- wprintf("%s ", colheader_label);
- }
- wprintf("<a href=\"readfwd?calview=day&year=%d&month=%d&day=%d\">"
- "%d</a></b><br />",
- tm.tm_year + 1900,
- tm.tm_mon + 1,
- tm.tm_mday,
- tm.tm_mday);
-
- /** put the data here, stupid */
- calendar_month_view_display_events(thetime);
-
- wprintf("</td>");
-
- /** After displaying Saturday, end the row */
- if ((i % 7) == 6) {
- wprintf("</tr>\n");
- }
-
- thetime += (time_t)86400; /** ahead 24 hours */
- }
-
- wprintf("</table>" /** end of inner table */
- "</td></tr></table>" /** end of outer table */
- "</div>\n");
-}
-
-/**
- * \brief view one month. brief view
- * \param year the year
- * \param month the month
- * \param day the actual day we want to see
- */
-void calendar_brief_month_view(int year, int month, int day) {
- struct tm starting_tm;
- struct tm tm;
- time_t thetime;
- int i;
- time_t previous_month;
- time_t next_month;
- char month_label[32];
-
- /** Determine what day to start.
- * First, back up to the 1st of the month...
- */
- memset(&starting_tm, 0, sizeof(struct tm));
- starting_tm.tm_year = year - 1900;
- starting_tm.tm_mon = month - 1;
- starting_tm.tm_mday = day;
- thetime = mktime(&starting_tm);
-
- memcpy(&tm, &starting_tm, sizeof(struct tm));
- while (tm.tm_mday != 1) {
- thetime = thetime - (time_t)86400; /* go back 24 hours */
- localtime_r(&thetime, &tm);
- }
-
- /** Determine previous and next months ... for links */
- previous_month = thetime - (time_t)864000L; /* back 10 days */
- next_month = thetime + (time_t)(31L * 86400L); /* ahead 31 days */
-
- /** Now back up until we're on a Sunday */
- localtime_r(&thetime, &tm);
- while (tm.tm_wday != 0) {
- thetime = thetime - (time_t)86400; /* go back 24 hours */
- localtime_r(&thetime, &tm);
- }
-
- /** Outer table (to get the background color) */
- wprintf("<div class=\"fix_scrollbar_bug\">"
- "<table width=100%% border=0 cellpadding=0 cellspacing=0 "
- "bgcolor=#204B78><TR><TD>\n");
-
- wprintf("<table width=100%% border=0 cellpadding=0 cellspacing=0><tr>\n");
-
- wprintf("<td align=center>");
-
- localtime_r(&previous_month, &tm);
- wprintf("<a href=\"readfwd?calview=month&year=%d&month=%d&day=1\">",
- (int)(tm.tm_year)+1900, tm.tm_mon + 1);
- wprintf("<img align=middle src=\"static/prevdate_32x.gif\" border=0></A>\n");
-
- wc_strftime(month_label, sizeof month_label, "%B", &tm);
- wprintf(" "
- "<font size=+1 color=\"#FFFFFF\">"
- "%s %d"
- "</font>"
- " ", month_label, year);
-
- localtime_r(&next_month, &tm);
- wprintf("<a href=\"readfwd?calview=month&year=%d&month=%d&day=1\">",
- (int)(tm.tm_year)+1900, tm.tm_mon + 1);
- wprintf("<img align=middle src=\"static/nextdate_32x.gif\" border=0></A>\n");
-
- wprintf("</td></tr></table>\n");
-
- /** Inner table (the real one) */
- wprintf("<table width=100%% border=0 cellpadding=1 cellspacing=1 "
- "bgcolor=#EEEECC><TR>");
- wprintf("</tr>\n");
- wprintf("<tr><td colspan=\"100%\">\n");
-
- /** Now do 35 days */
- for (i = 0; i < 35; ++i) {
- char weeknumber[255];
- char weekday_name[32];
- char *daycolor;
- localtime_r(&thetime, &tm);
-
-
- /** Before displaying Sunday, start a new CELL */
- if ((i % 7) == 0) {
- wc_strftime(&weeknumber[0], sizeof(weeknumber), "%U", &tm);
- wprintf("<table border='0' bgcolor=\"#EEEECC\" width='100%'> <tr><th colspan='4'>%s %s</th></tr>"
- " <tr><td>%s</td><td width='70%'>%s</td><td>%s</td><td>%s</td></tr>\n",
- _("Week"),
- weeknumber,
- _("Hours"),
- _("Subject"),
- _("Start"),
- _("End")
- );
- }
-
- daycolor=((tm.tm_mon != month-1) ? "DDDDDD" :
- ((tm.tm_wday==0 || tm.tm_wday==6) ? "EEEECC" :
- "FFFFFF"));
-
- /** Day Header */
- wc_strftime(weekday_name, sizeof weekday_name, "%A", &tm);
- wprintf("<tr><td bgcolor='%s' colspan='1' align='left'> %s,%i."
- "</td><td bgcolor='%s' colspan='3'><hr></td></tr>\n",
- daycolor,
- weekday_name,tm.tm_mday,
- daycolor);
-
- /** put the data of one day here, stupid */
- calendar_month_view_brief_events(thetime, daycolor);
-
-
- /** After displaying Saturday, end the row */
- if ((i % 7) == 6) {
- wprintf("</td></tr></table>\n");
- }
-
- thetime += (time_t)86400; /** ahead 24 hours */
- }
-
- wprintf("</table>" /** end of inner table */
- "</td></tr></table>" /** end of outer table */
- "</div>\n");
-}
-
-/**
- * \brief view one week
- * this should view just one week, but it's not here yet.
- * \todo ny implemented
- * \param year the year
- * \param month the month
- * \param day the day which we want to see the week around
- */
-void calendar_week_view(int year, int month, int day) {
- wprintf("<center><i>week view FIXME</i></center><br />\n");
-}
-
-
-/**
- * \brief display one day
- * Display events for a particular hour of a particular day.
- * (Specify hour < 0 to show "all day" events)
- * \param year the year
- * \param month the month
- * \param day the day
- * \param hour the hour we want to start displaying?????
- */
-void calendar_day_view_display_events(int year, int month,
- int day, int hour) {
- int i;
- icalproperty *p;
- struct icaltimetype t;
- time_t event_tt;
- struct tm *event_tm;
- int all_day_event = 0;
-
- if (WC->num_cal == 0) {
- // \todo FIXME wprintf("<br /><br /><br />\n");
- return;
- }
-
- for (i=0; i<(WC->num_cal); ++i) {
- p = icalcomponent_get_first_property(WC->disp_cal[i].cal,
- ICAL_DTSTART_PROPERTY);
- if (p != NULL) {
- t = icalproperty_get_dtstart(p);
- event_tt = icaltime_as_timet(t);
- if (t.is_date) {
- all_day_event = 1;
- }
- else {
- all_day_event = 0;
- }
-
- if (all_day_event) {
- event_tm = gmtime(&event_tt);
- }
- else {
- event_tm = localtime(&event_tt);
- }
-
- if ((event_tm->tm_year == (year-1900))
- && (event_tm->tm_mon == (month-1))
- && (event_tm->tm_mday == day)
- && ( ((event_tm->tm_hour == hour)&&(!t.is_date)) || ((hour<0)&&(t.is_date)) )
- ) {
-
-
- p = icalcomponent_get_first_property(
- WC->disp_cal[i].cal,
- ICAL_SUMMARY_PROPERTY);
- if (p != NULL) {
-
- if (all_day_event) {
- wprintf("<table border=1 cellpadding=2><TR>"
- "<td bgcolor=\"#CCCCCC\">"
- );
- }
-
- wprintf("<font size=-1>"
- "<a href=\"display_edit_event?msgnum=%ld&calview=day&year=%d&month=%d&day=%d\">",
- WC->disp_cal[i].cal_msgnum,
- year, month, day
- );
- escputs((char *)
- icalproperty_get_comment(p));
- wprintf("</a></font><br />\n");
-
- if (all_day_event) {
- wprintf("</td></tr></table>");
- }
- }
-
- }
-
-
- }
- }
-}
-
-
-/**
- * \brief view one day
- * \param year the year
- * \param month the month
- * \param day the day we want to display
- */
-void calendar_day_view(int year, int month, int day) {
- int hour;
- struct icaltimetype today, yesterday, tomorrow;
- char calhourformat[16];
- int daystart = 8;
- int dayend = 17;
- char daystart_str[16], dayend_str[16];
- struct tm d_tm;
- char d_str[128];
-
- get_preference("calhourformat", calhourformat, sizeof calhourformat);
- get_preference("daystart", daystart_str, sizeof daystart_str);
- if (strlen(daystart_str) > 0) daystart = atoi(daystart_str);
- get_preference("dayend", dayend_str, sizeof dayend_str);
- if (strlen(dayend_str) > 0) dayend = atoi(dayend_str);
-
-
- /** Figure out the dates for "yesterday" and "tomorrow" links */
-
- memset(&today, 0, sizeof(struct icaltimetype));
- today.year = year;
- today.month = month;
- today.day = day;
- today.is_date = 1;
-
- memcpy(&yesterday, &today, sizeof(struct icaltimetype));
- --yesterday.day;
- yesterday = icaltime_normalize(yesterday);
-
- memcpy(&tomorrow, &today, sizeof(struct icaltimetype));
- ++tomorrow.day;
- tomorrow = icaltime_normalize(tomorrow);
-
-
- /** Outer table (to get the background color) */
- wprintf("<div class=\"fix_scrollbar_bug\">"
- "<table width=100%% border=0 cellpadding=0 cellspacing=0 "
- "bgcolor=#204B78><tr><td>\n");
-
- /** Inner table (the real one) */
- wprintf("<table width=100%% border=0 cellpadding=1 cellspacing=1 "
- "bgcolor=#204B78><tr>\n");
-
- /** Innermost table (contains hours etc.) */
- wprintf("<td width=80%%>"
- "<table width=100%% border=0 cellpadding=1 cellspacing=1 "
- "bgcolor=#204B78>\n");
-
- /** Display events before 8:00 (hour=-1 is all-day events) */
- wprintf("<tr>"
- "<td bgcolor=\"#CCCCDD\" valign=middle width=10%%></td>"
- "<td bgcolor=\"#FFFFFF\" valign=top>");
- for (hour = (-1); hour <= (daystart-1); ++hour) {
- calendar_day_view_display_events(year, month, day, hour);
- }
- wprintf("</td></tr>\n");
-
- /** Now the middle of the day... */
- for (hour = daystart; hour <= dayend; ++hour) { /* could do HEIGHT=xx */
- wprintf("<tr height=30><td bgcolor=\"#CCCCDD\" align=middle "
- "valign=middle width=10%%>");
- wprintf("<a href=\"display_edit_event?msgnum=0"
- "&year=%d&month=%d&day=%d&hour=%d&minute=0\">",
- year, month, day, hour
- );
-
- if (!strcasecmp(calhourformat, "24")) {
- wprintf("%2d:00</a> ", hour);
- }
- else {
- wprintf("%d:00%s</a> ",
- (hour <= 12 ? hour : hour-12),
- (hour < 12 ? "am" : "pm")
- );
- }
-
- wprintf("</td><td bgcolor=\"#FFFFFF\" valign=top>");
-
- /* put the data here, stupid */
- calendar_day_view_display_events(year, month, day, hour);
-
- wprintf("</td></tr>\n");
- }
-
- /** Display events after 5:00... */
- wprintf("<tr>"
- "<td bgcolor=\"#CCCCDD\" valign=middle width=10%%></td>"
- "<td bgcolor=\"#FFFFFF\" valign=top>");
- for (hour = (dayend+1); hour <= 23; ++hour) {
- calendar_day_view_display_events(year, month, day, hour);
- }
- wprintf("</td></tr>\n");
-
-
- wprintf("</table>" /* end of innermost table */
- "</td>"
- );
-
- wprintf("<td width=20%% valign=top>"); /* begin stuff-on-the-right */
-
-
- /** Begin todays-date-with-left-and-right-arrows */
- wprintf("<table border=0 width=100%% "
- "cellspacing=0 cellpadding=0 bgcolor=\"#FFFFFF\">\n");
- wprintf("<tr>");
-
- /** Left arrow */
- wprintf("<td align=center>");
- wprintf("<a href=\"readfwd?calview=day&year=%d&month=%d&day=%d\">",
- yesterday.year, yesterday.month, yesterday.day);
- wprintf("<img align=middle src=\"static/prevdate_32x.gif\" border=0></A>");
- wprintf("</td>");
-
- /** Today's date */
- memset(&d_tm, 0, sizeof d_tm);
- d_tm.tm_year = year - 1900;
- d_tm.tm_mon = month - 1;
- d_tm.tm_mday = day;
- wc_strftime(d_str, sizeof d_str,
- "<td align=center>"
- "<font size=+2>%B</font><br />"
- "<font size=+3>%d</font><br />"
- "<font size=+2>%Y</font><br />"
- "</td>",
- &d_tm
- );
- wprintf("%s", d_str);
-
- /** Right arrow */
- wprintf("<td align=center>");
- wprintf("<a href=\"readfwd?calview=day&year=%d&month=%d&day=%d\">",
- tomorrow.year, tomorrow.month, tomorrow.day);
- wprintf("<img align=middle src=\"static/nextdate_32x.gif\""
- " border=0></A>\n");
- wprintf("</td>");
-
- wprintf("</tr></table>\n");
- /** End todays-date-with-left-and-right-arrows */
-
- /** \todo In the future we might want to put a month-o-matic here */
-
- wprintf("</font></center>\n");
-
- wprintf("</td>"); /** end stuff-on-the-right */
-
-
-
- wprintf("</tr></table>" /** end of inner table */
- "</td></tr></table></div>" /** end of outer table */
- );
-
-
-
-}
-
-/**
- * \brief Display today's events.
- */
-void calendar_summary_view(void) {
- int i;
- icalproperty *p;
- struct icaltimetype t;
- time_t event_tt;
- struct tm event_tm;
- struct tm today_tm;
- time_t now;
- int all_day_event = 0;
- char timestring[SIZ];
-
- if (WC->num_cal == 0) {
- return;
- }
-
- now = time(NULL);
- localtime_r(&now, &today_tm);
-
- for (i=0; i<(WC->num_cal); ++i) {
- p = icalcomponent_get_first_property(WC->disp_cal[i].cal,
- ICAL_DTSTART_PROPERTY);
- if (p != NULL) {
- t = icalproperty_get_dtstart(p);
- event_tt = icaltime_as_timet(t);
- if (t.is_date) {
- all_day_event = 1;
- }
- else {
- all_day_event = 0;
- }
- fmt_time(timestring, event_tt);
-
- if (all_day_event) {
- gmtime_r(&event_tt, &event_tm);
- }
- else {
- localtime_r(&event_tt, &event_tm);
- }
-
- if ( (event_tm.tm_year == today_tm.tm_year)
- && (event_tm.tm_mon == today_tm.tm_mon)
- && (event_tm.tm_mday == today_tm.tm_mday)
- ) {
-
-
- p = icalcomponent_get_first_property(
- WC->disp_cal[i].cal,
- ICAL_SUMMARY_PROPERTY);
- if (p != NULL) {
- escputs((char *)
- icalproperty_get_comment(p));
- wprintf(" (%s)<br />\n", timestring);
- }
- }
- }
- }
- free_calendar_buffer();
-}
-
-
-/**
- * \brief clean up ical memory
- * \todo this could get troubel with future ical versions
- */
-void free_calendar_buffer(void) {
- int i;
- if (WC->num_cal) for (i=0; i<(WC->num_cal); ++i) {
- icalcomponent_free(WC->disp_cal[i].cal);
- }
- WC->num_cal = 0;
- free(WC->disp_cal);
- WC->disp_cal = NULL;
-}
-
-
-
-/**
- * \brief do the whole calendar page
- * view any part of the calender. decide which way, etc.
- */
-void do_calendar_view(void) {
- time_t now;
- struct tm tm;
- int year, month, day;
- char calview[SIZ];
-
- /** In case no date was specified, go with today */
- now = time(NULL);
- localtime_r(&now, &tm);
- year = tm.tm_year + 1900;
- month = tm.tm_mon + 1;
- day = tm.tm_mday;
-
- /** Now see if a date was specified */
- if (strlen(bstr("year")) > 0) year = atoi(bstr("year"));
- if (strlen(bstr("month")) > 0) month = atoi(bstr("month"));
- if (strlen(bstr("day")) > 0) day = atoi(bstr("day"));
-
- /** How would you like that cooked? */
- if (strlen(bstr("calview")) > 0) {
- strcpy(calview, bstr("calview"));
- }
- else {
- strcpy(calview, "month");
- }
-
- /** Display the selected view */
- if (!strcasecmp(calview, "day")) {
- calendar_day_view(year, month, day);
- }
- else if (!strcasecmp(calview, "week")) {
- calendar_week_view(year, month, day);
- }
- else {
- if (WC->wc_view == VIEW_CALBRIEF) {
- calendar_brief_month_view(year, month, day);
- }
- else {
- calendar_month_view(year, month, day);
- }
- }
-
- /** Free the calendar stuff */
- free_calendar_buffer();
-
-}
-
-
-/**
- * \brief get task due date
- * Helper function for do_tasks_view().
- * \param vtodo a task to get the due date
- * \return the date/time due.
- */
-time_t get_task_due_date(icalcomponent *vtodo) {
- icalproperty *p;
-
- if (vtodo == NULL) {
- return(0L);
- }
-
- /**
- * If we're looking at a fully encapsulated VCALENDAR
- * rather than a VTODO component, recurse into the data
- * structure until we get a VTODO.
- */
- if (icalcomponent_isa(vtodo) == ICAL_VCALENDAR_COMPONENT) {
- return get_task_due_date(
- icalcomponent_get_first_component(
- vtodo, ICAL_VTODO_COMPONENT
- )
- );
- }
-
- p = icalcomponent_get_first_property(vtodo, ICAL_DUE_PROPERTY);
- if (p != NULL) {
- return(icaltime_as_timet(icalproperty_get_due(p)));
- }
- else {
- return(0L);
- }
-}
-
-
-/**
- * \brief Compare the due dates of two tasks (this is for sorting)
- * \param task1 first task to compare
- * \param task2 second task to compare
- */
-int task_due_cmp(const void *task1, const void *task2) {
- time_t t1;
- time_t t2;
-
- t1 = get_task_due_date(((struct disp_cal *)task1)->cal);
- t2 = get_task_due_date(((struct disp_cal *)task2)->cal);
-
- if (t1 < t2) return(-1);
- if (t1 > t2) return(1);
- return(0);
-}
-
-
-
-
-/**
- * \brief do the whole task view stuff
- */
-void do_tasks_view(void) {
- int i;
- time_t due;
- int bg = 0;
- char buf[SIZ];
- icalproperty *p;
-
- wprintf("<div class=\"fix_scrollbar_bug\">"
- "<table border=0 cellspacing=0 width=100%% bgcolor=\"#FFFFFF\">\n<tr>\n"
- "<th>");
- wprintf(_("Name of task"));
- wprintf("</th><th>");
- wprintf(_("Date due"));
- wprintf("</th></tr>\n"
- );
-
- /** Sort them if necessary */
- if (WC->num_cal > 1) {
- qsort(WC->disp_cal,
- WC->num_cal,
- sizeof(struct disp_cal),
- task_due_cmp
- );
- }
-
- if (WC->num_cal) for (i=0; i<(WC->num_cal); ++i) {
-
- bg = 1 - bg;
- wprintf("<tr bgcolor=\"#%s\"><td>",
- (bg ? "DDDDDD" : "FFFFFF")
- );
-
- p = icalcomponent_get_first_property(WC->disp_cal[i].cal,
- ICAL_SUMMARY_PROPERTY);
- wprintf("<a href=\"display_edit_task?msgnum=%ld&taskrm=",
- WC->disp_cal[i].cal_msgnum );
- urlescputs(WC->wc_roomname);
- wprintf("\">");
- wprintf("<img align=middle "
- "src=\"static/taskmanag_16x.gif\" border=0> ");
- if (p != NULL) {
- escputs((char *)icalproperty_get_comment(p));
- }
- wprintf("</a>\n");
- wprintf("</td>\n");
-
- due = get_task_due_date(WC->disp_cal[i].cal);
- fmt_date(buf, due, 0);
- wprintf("<td><font");
- if (due < time(NULL)) {
- wprintf(" color=\"#FF0000\"");
- }
- wprintf(">%s</font></td></tr>\n", buf);
- }
-
- wprintf("</table></div>\n");
-
- /** Free the list */
- free_calendar_buffer();
-
-}
-
-#endif /* WEBCIT_WITH_CALENDAR_SERVICE */
-
-/** @} */
+++ /dev/null
-/*
- * $Id$
- */
-/**
- * \defgroup WebServerII some of the webserver stuff.
- * This is the other half of the webserver. It handles the task of hooking
- * up HTTP requests with the sessions they belong to, using HTTP cookies to
- * keep track of things. If the HTTP request doesn't belong to any currently
- * active session, a new session is started.
- * \ingroup WebcitHttpServer
- *
- */
-/*@{*/
-#include "webcit.h"
-#include "webserver.h"
-
-/** Only one thread may manipulate SessionList at a time... */
-pthread_mutex_t SessionListMutex;
-
-struct wcsession *SessionList = NULL; /**< our sessions ????*/
-
-pthread_key_t MyConKey; /**< TSD key for MySession() */
-
-
-/**
- * \brief free the memory used for viewing atachments
- * \param sess the session object to destroy
- */
-void free_attachments(struct wcsession *sess) {
- struct wc_attachment *att;
-
- while (sess->first_attachment != NULL) {
- att = sess->first_attachment;
- sess->first_attachment = sess->first_attachment->next;
- free(att->data);
- free(att);
- }
-}
-
-/**
- * \brief what??????
- */
-void do_housekeeping(void)
-{
- struct wcsession *sptr, *ss;
- struct wcsession *sessions_to_kill = NULL;
- int num_sessions = 0;
- static int num_threads = MIN_WORKER_THREADS;
-
- /**
- * Lock the session list, moving any candidates for euthanasia into
- * a separate list.
- */
- pthread_mutex_lock(&SessionListMutex);
- num_sessions = 0;
- for (sptr = SessionList; sptr != NULL; sptr = sptr->next) {
- ++num_sessions;
-
- /** Kill idle sessions */
- if ((time(NULL) - (sptr->lastreq)) >
- (time_t) WEBCIT_TIMEOUT) {
- sptr->killthis = 1;
- }
-
- /** Remove sessions flagged for kill */
- if (sptr->killthis) {
-
- /** remove session from linked list */
- if (sptr == SessionList) {
- SessionList = SessionList->next;
- }
- else for (ss=SessionList;ss!=NULL;ss=ss->next) {
- if (ss->next == sptr) {
- ss->next = ss->next->next;
- }
- }
-
- sptr->next = sessions_to_kill;
- sessions_to_kill = sptr;
- }
- }
- pthread_mutex_unlock(&SessionListMutex);
-
- /**
- * Now free up and destroy the culled sessions.
- */
- while (sessions_to_kill != NULL) {
- lprintf(3, "Destroying session %d\n", sessions_to_kill->wc_session);
- pthread_mutex_lock(&sessions_to_kill->SessionMutex);
- close(sessions_to_kill->serv_sock);
- close(sessions_to_kill->chat_sock);
- if (sessions_to_kill->preferences != NULL) {
- free(sessions_to_kill->preferences);
- }
- if (sessions_to_kill->cache_fold != NULL) {
- free(sessions_to_kill->cache_fold);
- }
- free_attachments(sessions_to_kill);
- free_march_list(sessions_to_kill);
- pthread_mutex_unlock(&sessions_to_kill->SessionMutex);
- sptr = sessions_to_kill->next;
- free(sessions_to_kill);
- sessions_to_kill = sptr;
- --num_sessions;
- }
-
- /**
- * If there are more sessions than threads, then we should spawn
- * more threads ... up to a predefined maximum.
- */
- while ( (num_sessions > num_threads)
- && (num_threads <= MAX_WORKER_THREADS) ) {
- spawn_another_worker_thread();
- ++num_threads;
- lprintf(3, "There are %d sessions and %d threads active.\n",
- num_sessions, num_threads);
- }
-}
-
-
-/**
- * \brief Wake up occasionally and clean house
- */
-void housekeeping_loop(void)
-{
- while (1) {
- sleeeeeeeeeep(HOUSEKEEPING);
- do_housekeeping();
- }
-}
-
-
-/**
- * \brief Create a Session id
- * Generate a unique WebCit session ID (which is not the same thing as the
- * Citadel session ID).
- *
- * \todo FIXME ... ensure that session number is truly unique
- *
- */
-int GenerateSessionID(void)
-{
- static int seq = (-1);
-
- if (seq < 0) {
- seq = (int) time(NULL);
- }
-
- return ++seq;
-}
-
-
-/**
- * \brief Collapse multiple cookies on one line
- * \param sock a socket?
- * \param buf some bunch of chars?
- * \param hold hold what?
- */
-int req_gets(int sock, char *buf, char *hold)
-{
- int a;
-
- if (strlen(hold) == 0) {
- strcpy(buf, "");
- a = client_getln(sock, buf, SIZ);
- if (a<1) return(-1);
- } else {
- safestrncpy(buf, hold, SIZ);
- }
- strcpy(hold, "");
-
- if (!strncasecmp(buf, "Cookie: ", 8)) {
- for (a = 0; a < strlen(buf); ++a)
- if (buf[a] == ';') {
- sprintf(hold, "Cookie: %s", &buf[a + 1]);
- buf[a] = 0;
- while (isspace(hold[8]))
- strcpy(&hold[8], &hold[9]);
- return(0);
- }
- }
-
- return(0);
-}
-
-/**
- * \brief close some fd for some reason???
- * \param fd the fd to close??????
- * lingering_close() a`la Apache. see
- * http://www.apache.org/docs/misc/fin_wait_2.html for rationale
- */
-
-int lingering_close(int fd)
-{
- char buf[SIZ];
- int i;
- fd_set set;
- struct timeval tv, start;
-
- gettimeofday(&start, NULL);
- shutdown(fd, 1);
- do {
- do {
- gettimeofday(&tv, NULL);
- tv.tv_sec = SLEEPING - (tv.tv_sec - start.tv_sec);
- tv.tv_usec = start.tv_usec - tv.tv_usec;
- if (tv.tv_usec < 0) {
- tv.tv_sec--;
- tv.tv_usec += 1000000;
- }
- FD_ZERO(&set);
- FD_SET(fd, &set);
- i = select(fd + 1, &set, NULL, NULL, &tv);
- } while (i == -1 && errno == EINTR);
-
- if (i <= 0)
- break;
-
- i = read(fd, buf, sizeof buf);
- } while (i != 0 && (i != -1 || errno == EINTR));
-
- return close(fd);
-}
-
-
-
-/**
- * \brief sanity requests
- * Check for bogus requests coming from brain-dead Windows boxes.
- *
- * \param http_cmd The HTTP request to check
- */
-int is_bogus(char *http_cmd) {
- char *url;
-
- url = strstr(http_cmd, " ");
- if (url == NULL) return(1);
- ++url;
-
- /** Worms and trojans and viruses, oh my! */
- if (!strncasecmp(url, "/scripts/root.exe", 17)) return(2);
- if (!strncasecmp(url, "/c/winnt", 8)) return(2);
- if (!strncasecmp(url, "/MSADC/", 7)) return(2);
-
- /** Broken Microsoft DAV implementation */
- if (!strncasecmp(url, "/_vti", 5)) return(3);
-
- return(0); /* probably ok */
-}
-
-
-
-/**
- * \brief handle one request
- * This loop gets called once for every HTTP connection made to WebCit. At
- * this entry point we have an HTTP socket with a browser allegedly on the
- * other end, but we have not yet bound to a WebCit session.
- *
- * The job of this function is to locate the correct session and bind to it,
- * or create a session if necessary and bind to it, then run the WebCit
- * transaction loop. Afterwards, we unbind from the session. When this
- * function returns, the worker thread is then free to handle another
- * transaction.
- * \param sock the socket we will put our answer to
- */
-void context_loop(int sock)
-{
- struct httprequest *req = NULL;
- struct httprequest *last = NULL;
- struct httprequest *hptr;
- char buf[SIZ], hold[SIZ];
- int desired_session = 0;
- int got_cookie = 0;
- int gzip_ok = 0;
- struct wcsession *TheSession, *sptr;
- char httpauth_string[1024];
- char httpauth_user[1024];
- char httpauth_pass[1024];
- char accept_language[256];
- char *ptr = NULL;
- int session_is_new = 0;
-
- strcpy(httpauth_string, "");
- strcpy(httpauth_user, DEFAULT_HTTPAUTH_USER);
- strcpy(httpauth_pass, DEFAULT_HTTPAUTH_PASS);
-
- /**
- * Find out what it is that the web browser is asking for
- */
- memset(hold, 0, sizeof(hold));
- do {
- if (req_gets(sock, buf, hold) < 0) return;
-
- /**
- * Can we compress?
- */
- if (!strncasecmp(buf, "Accept-encoding:", 16)) {
- if (strstr(&buf[16], "gzip")) {
- gzip_ok = 1;
- }
- }
-
- /**
- * Browser-based sessions use cookies for session authentication
- */
- if (!strncasecmp(buf, "Cookie: webcit=", 15)) {
- cookie_to_stuff(&buf[15], &desired_session,
- NULL, 0, NULL, 0, NULL, 0);
- got_cookie = 1;
- }
-
- /**
- * GroupDAV-based sessions use HTTP authentication
- */
- if (!strncasecmp(buf, "Authorization: Basic ", 21)) {
- CtdlDecodeBase64(httpauth_string, &buf[21], strlen(&buf[21]));
- extract_token(httpauth_user, httpauth_string, 0, ':', sizeof httpauth_user);
- extract_token(httpauth_pass, httpauth_string, 1, ':', sizeof httpauth_pass);
- }
-
- if (!strncasecmp(buf, "If-Modified-Since: ", 19)) {
- if_modified_since = httpdate_to_timestamp(&buf[19]);
- }
-
- if (!strncasecmp(buf, "Accept-Language: ", 17)) {
- safestrncpy(accept_language, &buf[17], sizeof accept_language);
- }
-
- /**
- * Read in the request
- */
- hptr = (struct httprequest *)
- malloc(sizeof(struct httprequest));
- if (req == NULL)
- req = hptr;
- else
- last->next = hptr;
- hptr->next = NULL;
- last = hptr;
-
- safestrncpy(hptr->line, buf, sizeof hptr->line);
-
- } while (strlen(buf) > 0);
-
- /**
- * If the request is prefixed by "/webcit" then chop that off. This
- * allows a front end web server to forward all /webcit requests to us
- * while still using the same web server port for other things.
- */
-
- ptr = strstr(req->line, " /webcit "); /*< Handle "/webcit" */
- if (ptr != NULL) {
- strcpy(ptr+2, ptr+8);
- }
-
- ptr = strstr(req->line, " /webcit"); /*< Handle "/webcit/" */
- if (ptr != NULL) {
- strcpy(ptr+1, ptr+8);
- }
-
- /** Begin parsing the request. */
-
- safestrncpy(buf, req->line, sizeof buf);
- lprintf(5, "HTTP: %s\n", buf);
-
- /** Check for bogus requests */
- if (is_bogus(buf)) {
- strcpy(req->line, "GET /404 HTTP/1.1");
- strcpy(buf, "GET /404 HTTP/1.1");
- }
-
- /**
- * Strip out the method, leaving the URL up front...
- */
- remove_token(buf, 0, ' ');
- if (buf[1]==' ') buf[1]=0;
-
- /**
- * While we're at it, gracefully handle requests for the
- * robots.txt and favicon.ico files.
- */
- if (!strncasecmp(buf, "/robots.txt", 11)) {
- strcpy(req->line, "GET /static/robots.txt"
- "?force_close_session=yes HTTP/1.1");
- }
- else if (!strncasecmp(buf, "/favicon.ico", 12)) {
- strcpy(req->line, "GET /static/favicon.ico");
- }
-
- /**
- * These are the URL's which may be executed without a
- * session cookie already set. If it's not one of these,
- * force the session to close because cookies are
- * probably disabled on the client browser.
- */
- else if ( (strcmp(buf, "/"))
- && (strncasecmp(buf, "/listsub", 8))
- && (strncasecmp(buf, "/freebusy", 9))
- && (strncasecmp(buf, "/do_logout", 10))
- && (strncasecmp(buf, "/groupdav", 9))
- && (strncasecmp(buf, "/static", 7))
- && (strncasecmp(buf, "/rss", 4))
- && (strncasecmp(buf, "/404", 4))
- && (got_cookie == 0)) {
- strcpy(req->line, "GET /static/nocookies.html"
- "?force_close_session=yes HTTP/1.1");
- }
-
- /**
- * See if there's an existing session open with the desired ID or user/pass
- */
- TheSession = NULL;
-
- if (TheSession == NULL) {
- pthread_mutex_lock(&SessionListMutex);
- for (sptr = SessionList; sptr != NULL; sptr = sptr->next) {
-
- /** If HTTP-AUTH, look for a session with matching credentials */
- if ( (strlen(httpauth_user) > 0)
- &&(!strcasecmp(sptr->httpauth_user, httpauth_user))
- &&(!strcasecmp(sptr->httpauth_pass, httpauth_pass)) ) {
- TheSession = sptr;
- }
-
- /** If cookie-session, look for a session with matching session ID */
- if ( (desired_session != 0) && (sptr->wc_session == desired_session)) {
- TheSession = sptr;
- }
-
- }
- pthread_mutex_unlock(&SessionListMutex);
- }
-
- /**
- * Create a new session if we have to
- */
- if (TheSession == NULL) {
- lprintf(3, "Creating a new session\n");
- TheSession = (struct wcsession *)
- malloc(sizeof(struct wcsession));
- memset(TheSession, 0, sizeof(struct wcsession));
- TheSession->serv_sock = (-1);
- TheSession->chat_sock = (-1);
- TheSession->wc_session = GenerateSessionID();
- strcpy(TheSession->httpauth_user, httpauth_user);
- strcpy(TheSession->httpauth_pass, httpauth_pass);
- pthread_mutex_init(&TheSession->SessionMutex, NULL);
- pthread_mutex_lock(&SessionListMutex);
- TheSession->next = SessionList;
- SessionList = TheSession;
- pthread_mutex_unlock(&SessionListMutex);
- session_is_new = 1;
- }
-
- /**
- * A future improvement might be to check the session integrity
- * at this point before continuing.
- */
-
- /**
- * Bind to the session and perform the transaction
- */
- pthread_mutex_lock(&TheSession->SessionMutex); /*< bind */
- pthread_setspecific(MyConKey, (void *)TheSession);
- TheSession->http_sock = sock;
- TheSession->lastreq = time(NULL); /*< log */
- TheSession->gzip_ok = gzip_ok;
-#ifdef ENABLE_NLS
- if (session_is_new) {
- httplang_to_locale(accept_language);
- }
- go_selected_language(); /*< set locale */
-#endif
- session_loop(req); /*< do transaction */
-#ifdef ENABLE_NLS
- stop_selected_language(); /*< unset locale */
-#endif
- pthread_mutex_unlock(&TheSession->SessionMutex); /*< unbind */
-
- /** Free the request buffer */
- while (req != NULL) {
- hptr = req->next;
- free(req);
- req = hptr;
- }
-
- /**
- * Free up any session-local substitution variables which
- * were set during this transaction
- */
- clear_local_substs();
-}
-/*@}*/
+++ /dev/null
-/*
- * $Id$
- */
-/**
- * \defgroup CookieConversion Grep Cookies
- * Utility functions which convert the HTTP cookie format we use to and
- * from user/password/room strings.
- *
- * \ingroup WebcitHttpServer
- */
-/*@{*/
-#include "webcit.h"
-
-
-#define TRUE 1 /**< for sure? */
-#define FALSE 0 /**< nope. */
-
-typedef unsigned char byte; /**< Byte type */
-
-/**
- * \brief find cookie
- * Pack all session info into one easy-to-digest cookie. Healthy and delicious!
- * \param cookie cookie string to create???
- * \param session the session we want to convert into a cookie
- * \param user the user to be associated with the cookie
- * \param pass his passphrase
- * \param room the room he wants to enter
- */
-void stuff_to_cookie(char *cookie, int session,
- char *user, char *pass, char *room)
-{
- char buf[SIZ];
- int i;
-
- sprintf(buf, "%d|%s|%s|%s|", session, user, pass, room);
- strcpy(cookie, "");
- for (i=0; i<strlen(buf); ++i) {
- sprintf(&cookie[i*2], "%02X", buf[i]);
- }
-}
-
-/**
- * \brief Convert unpacked hex string to an integer
- * \param in Input hex string
- * \param len the length of the string
- * \return the corrosponding integer value
- */
-int xtoi(char *in, size_t len)
-{
- int val = 0;
- char c = 0;
- while (isxdigit((byte) *in) && (len-- > 0))
- {
- c = *in++;
- val <<= 4;
- val += isdigit((unsigned char)c)
- ? (c - '0')
- : (tolower((unsigned char)c) - 'a' + 10);
- }
- return val;
-}
-
-/**
- * \brief Extract all that fun stuff out of the cookie.
- * \param cookie the cookie string
- * \param session the corrosponding session to return
- * \param user the user string
- * \param user_len the user stringlength
- * \param pass the passphrase
- * \param pass_len length of the passphrase string
- * \param room the room he is in
- * \param room_len the length of the room string
- */
-void cookie_to_stuff(char *cookie, int *session,
- char *user, size_t user_len,
- char *pass, size_t pass_len,
- char *room, size_t room_len)
-{
- char buf[SIZ];
- int i, len;
-
- strcpy(buf, "");
- len = strlen(cookie) * 2 ;
- for (i=0; i<len; ++i) {
- buf[i] = xtoi(&cookie[i*2], 2);
- buf[i+1] = 0;
- }
-
- if (session != NULL)
- *session = extract_int(buf, 0);
- if (user != NULL)
- extract_token(user, buf, 1, '|', user_len);
- if (pass != NULL)
- extract_token(pass, buf, 2, '|', pass_len);
- if (room != NULL)
- extract_token(room, buf, 3, '|', room_len);
-}
-/*@}*/
+++ /dev/null
-/*
- * $Id$
- */
-/**
- * \defgroup https Provides HTTPS, when the OpenSSL library is available.
- * \ingroup WebcitHttpServer
- */
-
-/*@{*/
-#ifdef HAVE_OPENSSL
-
-#include "webcit.h"
-#include "webserver.h"
-/** \todo dirify */
-/** where to find the keys */
-#define CTDL_CRYPTO_DIR "./keys"
-#define CTDL_KEY_PATH CTDL_CRYPTO_DIR "/citadel.key" /**< the key */
-#define CTDL_CSR_PATH CTDL_CRYPTO_DIR "/citadel.csr" /**< the csr file */
-#define CTDL_CER_PATH CTDL_CRYPTO_DIR "/citadel.cer" /**< the cer file */
-#define SIGN_DAYS 365 /**< how long our certificate should live */
-
-SSL_CTX *ssl_ctx; /**< SSL context */
-pthread_mutex_t **SSLCritters; /**< Things needing locking */
-
-pthread_key_t ThreadSSL; /**< Per-thread SSL context */
-
-/**
- * \brief what?????
- * \return thread id???
- */
-static unsigned long id_callback(void)
-{
- return (unsigned long) pthread_self();
-}
-
-/**
- * \brief initialize ssl engine
- * load certs and initialize openssl internals
- */
-void init_ssl(void)
-{
- SSL_METHOD *ssl_method;
- RSA *rsa=NULL;
- X509_REQ *req = NULL;
- X509 *cer = NULL;
- EVP_PKEY *pk = NULL;
- EVP_PKEY *req_pkey = NULL;
- X509_NAME *name = NULL;
- FILE *fp;
- char buf[SIZ];
-
- if (!access("/var/run/egd-pool", F_OK))
- RAND_egd("/var/run/egd-pool");
-
- if (!RAND_status()) {
- lprintf(3,
- "PRNG not adequately seeded, won't do SSL/TLS\n");
- return;
- }
- SSLCritters =
- malloc(CRYPTO_num_locks() * sizeof(pthread_mutex_t *));
- if (!SSLCritters) {
- lprintf(1, "citserver: can't allocate memory!!\n");
- /* Nothing's been initialized, just die */
- exit(1);
- } else {
- int a;
-
- for (a = 0; a < CRYPTO_num_locks(); a++) {
- SSLCritters[a] = malloc(sizeof(pthread_mutex_t));
- if (!SSLCritters[a]) {
- lprintf(1,
- "citserver: can't allocate memory!!\n");
- /** Nothing's been initialized, just die */
- exit(1);
- }
- pthread_mutex_init(SSLCritters[a], NULL);
- }
- }
-
- /**
- * Initialize SSL transport layer
- */
- SSL_library_init();
- SSL_load_error_strings();
- ssl_method = SSLv23_server_method();
- if (!(ssl_ctx = SSL_CTX_new(ssl_method))) {
- lprintf(3, "SSL_CTX_new failed: %s\n",
- ERR_reason_error_string(ERR_get_error()));
- return;
- }
-
- CRYPTO_set_locking_callback(ssl_lock);
- CRYPTO_set_id_callback(id_callback);
-
- /**
- * Get our certificates in order. \todo dirify. this is a setup job.
- * First, create the key/cert directory if it's not there already...
- */
- mkdir(CTDL_CRYPTO_DIR, 0700);
-
- /**
- * Before attempting to generate keys/certificates, first try
- * link to them from the Citadel server if it's on the same host.
- * We ignore any error return because it either meant that there
- * was nothing in Citadel to link from (in which case we just
- * generate new files) or the target files already exist (which
- * is not fatal either). \todo dirify
- */
- if (!strcasecmp(ctdlhost, "uds")) {
- sprintf(buf, "%s/keys/citadel.key", ctdlport);
- symlink(buf, CTDL_KEY_PATH);
- sprintf(buf, "%s/keys/citadel.csr", ctdlport);
- symlink(buf, CTDL_CSR_PATH);
- sprintf(buf, "%s/keys/citadel.cer", ctdlport);
- symlink(buf, CTDL_CER_PATH);
- }
-
- /**
- * If we still don't have a private key, generate one.
- */
- if (access(CTDL_KEY_PATH, R_OK) != 0) {
- lprintf(5, "Generating RSA key pair.\n");
- rsa = RSA_generate_key(1024, /**< modulus size */
- 65537, /**< exponent */
- NULL, /**< no callback */
- NULL); /**< no callback */
- if (rsa == NULL) {
- lprintf(3, "Key generation failed: %s\n",
- ERR_reason_error_string(ERR_get_error()));
- }
- if (rsa != NULL) {
- fp = fopen(CTDL_KEY_PATH, "w");
- if (fp != NULL) {
- chmod(CTDL_KEY_PATH, 0600);
- if (PEM_write_RSAPrivateKey(fp, /**< the file */
- rsa, /**< the key */
- NULL, /**< no enc */
- NULL, /**< no passphr */
- 0, /**< no passphr */
- NULL, /**< no callbk */
- NULL /**< no callbk */
- ) != 1) {
- lprintf(3, "Cannot write key: %s\n",
- ERR_reason_error_string(ERR_get_error()));
- unlink(CTDL_KEY_PATH);
- }
- fclose(fp);
- }
- RSA_free(rsa);
- }
- }
-
- /**
- * Generate a CSR if we don't have one.
- */
- if (access(CTDL_CSR_PATH, R_OK) != 0) {
- lprintf(5, "Generating a certificate signing request.\n");
-
- /**
- * Read our key from the file. No, we don't just keep this
- * in memory from the above key-generation function, because
- * there is the possibility that the key was already on disk
- * and we didn't just generate it now.
- */
- fp = fopen(CTDL_KEY_PATH, "r");
- if (fp) {
- rsa = PEM_read_RSAPrivateKey(fp, NULL, NULL, NULL);
- fclose(fp);
- }
-
- if (rsa) {
-
- /** Create a public key from the private key */
- if (pk=EVP_PKEY_new(), pk != NULL) {
- EVP_PKEY_assign_RSA(pk, rsa);
- if (req = X509_REQ_new(), req != NULL) {
-
- /** Set the public key */
- X509_REQ_set_pubkey(req, pk);
- X509_REQ_set_version(req, 0L);
-
- name = X509_REQ_get_subject_name(req);
-
- /** Tell it who we are */
-
- /* \todo whats this?
- X509_NAME_add_entry_by_txt(name, "C",
- MBSTRING_ASC, "US", -1, -1, 0);
-
- X509_NAME_add_entry_by_txt(name, "ST",
- MBSTRING_ASC, "New York", -1, -1, 0);
-
- X509_NAME_add_entry_by_txt(name, "L",
- MBSTRING_ASC, "Mount Kisco", -1, -1, 0);
- */
-
- X509_NAME_add_entry_by_txt(name, "O",
- MBSTRING_ASC, "FIXME.FIXME.org", -1, -1, 0);
-
- X509_NAME_add_entry_by_txt(name, "OU",
- MBSTRING_ASC, "Citadel server", -1, -1, 0);
-
- X509_NAME_add_entry_by_txt(name, "CN",
- MBSTRING_ASC, "FIXME.FIXME.org", -1, -1, 0);
-
- X509_REQ_set_subject_name(req, name);
-
- /** Sign the CSR */
- if (!X509_REQ_sign(req, pk, EVP_md5())) {
- lprintf(3, "X509_REQ_sign(): error\n");
- }
- else {
- /** Write it to disk. */
- fp = fopen(CTDL_CSR_PATH, "w");
- if (fp != NULL) {
- chmod(CTDL_CSR_PATH, 0600);
- PEM_write_X509_REQ(fp, req);
- fclose(fp);
- }
- }
-
- X509_REQ_free(req);
- }
- }
-
- RSA_free(rsa);
- }
-
- else {
- lprintf(3, "Unable to read private key.\n");
- }
- }
-
-
-
- /**
- * Generate a self-signed certificate if we don't have one.
- */
- if (access(CTDL_CER_PATH, R_OK) != 0) {
- lprintf(5, "Generating a self-signed certificate.\n");
-
- /** Same deal as before: always read the key from disk because
- * it may or may not have just been generated.
- */
- fp = fopen(CTDL_KEY_PATH, "r");
- if (fp) {
- rsa = PEM_read_RSAPrivateKey(fp, NULL, NULL, NULL);
- fclose(fp);
- }
-
- /** This also holds true for the CSR. */
- req = NULL;
- cer = NULL;
- pk = NULL;
- if (rsa) {
- if (pk=EVP_PKEY_new(), pk != NULL) {
- EVP_PKEY_assign_RSA(pk, rsa);
- }
-
- fp = fopen(CTDL_CSR_PATH, "r");
- if (fp) {
- req = PEM_read_X509_REQ(fp, NULL, NULL, NULL);
- fclose(fp);
- }
-
- if (req) {
- if (cer = X509_new(), cer != NULL) {
-
- ASN1_INTEGER_set(X509_get_serialNumber(cer), 0);
- X509_set_issuer_name(cer, req->req_info->subject);
- X509_set_subject_name(cer, req->req_info->subject);
- X509_gmtime_adj(X509_get_notBefore(cer), 0);
- X509_gmtime_adj(X509_get_notAfter(cer),(long)60*60*24*SIGN_DAYS);
-
- req_pkey = X509_REQ_get_pubkey(req);
- X509_set_pubkey(cer, req_pkey);
- EVP_PKEY_free(req_pkey);
-
- /** Sign the cert */
- if (!X509_sign(cer, pk, EVP_md5())) {
- lprintf(3, "X509_sign(): error\n");
- }
- else {
- /** Write it to disk. */
- fp = fopen(CTDL_CER_PATH, "w");
- if (fp != NULL) {
- chmod(CTDL_CER_PATH, 0600);
- PEM_write_X509(fp, cer);
- fclose(fp);
- }
- }
- X509_free(cer);
- }
- }
-
- RSA_free(rsa);
- }
- }
-
- /**
- * Now try to bind to the key and certificate.
- * Note that we use SSL_CTX_use_certificate_chain_file() which allows
- * the certificate file to contain intermediate certificates.
- */
- SSL_CTX_use_certificate_chain_file(ssl_ctx, CTDL_CER_PATH);
- SSL_CTX_use_PrivateKey_file(ssl_ctx, CTDL_KEY_PATH, SSL_FILETYPE_PEM);
- if ( !SSL_CTX_check_private_key(ssl_ctx) ) {
- lprintf(3, "Cannot install certificate: %s\n",
- ERR_reason_error_string(ERR_get_error()));
- }
-
-}
-
-
-/**
- * \brief starts SSL/TLS encryption for the current session.
- * \param sock the socket connection
- * \return Zero if the SSL/TLS handshake succeeded, non-zero otherwise.
- */
-int starttls(int sock) {
- int retval, bits, alg_bits;
- SSL *newssl;
-
- pthread_setspecific(ThreadSSL, NULL);
-
- if (!ssl_ctx) {
- return(1);
- }
- if (!(newssl = SSL_new(ssl_ctx))) {
- lprintf(3, "SSL_new failed: %s\n",
- ERR_reason_error_string(ERR_get_error()));
- return(2);
- }
- if (!(SSL_set_fd(newssl, sock))) {
- lprintf(3, "SSL_set_fd failed: %s\n",
- ERR_reason_error_string(ERR_get_error()));
- SSL_free(newssl);
- return(3);
- }
- retval = SSL_accept(newssl);
- if (retval < 1) {
- /**
- * Can't notify the client of an error here; they will
- * discover the problem at the SSL layer and should
- * revert to unencrypted communications.
- */
- long errval;
-
- errval = SSL_get_error(newssl, retval);
- lprintf(3, "SSL_accept failed: %s\n",
- ERR_reason_error_string(ERR_get_error()));
- SSL_free(newssl);
- newssl = NULL;
- return(4);
- }
- BIO_set_close(newssl->rbio, BIO_NOCLOSE);
- bits =
- SSL_CIPHER_get_bits(SSL_get_current_cipher(newssl),
- &alg_bits);
- lprintf(5, "SSL/TLS using %s on %s (%d of %d bits)\n",
- SSL_CIPHER_get_name(SSL_get_current_cipher(newssl)),
- SSL_CIPHER_get_version(SSL_get_current_cipher(newssl)),
- bits, alg_bits);
-
- pthread_setspecific(ThreadSSL, newssl);
- return(0);
-}
-
-
-
-/**
- * \brief shuts down the TLS connection
- *
- * WARNING: This may make your session vulnerable to a known plaintext
- * attack in the current implmentation.
- */
-void endtls(void)
-{
- if (THREADSSL == NULL) return;
-
- lprintf(5, "Ending SSL/TLS\n");
- SSL_shutdown(THREADSSL);
- SSL_free(THREADSSL);
- pthread_setspecific(ThreadSSL, NULL);
-}
-
-
-/**
- * \brief callback for OpenSSL mutex locks
- * \param mode which mode??????
- * \param n how many???
- * \param file which filename ???
- * \param line what line????
- */
-void ssl_lock(int mode, int n, const char *file, int line)
-{
- if (mode & CRYPTO_LOCK)
- pthread_mutex_lock(SSLCritters[n]);
- else
- pthread_mutex_unlock(SSLCritters[n]);
-}
-
-/**
- * \brief Send binary data to the client encrypted.
- * \param buf chars to send to the client
- * \param nbytes how many chars
- */
-void client_write_ssl(char *buf, int nbytes)
-{
- int retval;
- int nremain;
- char junk[1];
-
- if (THREADSSL == NULL) return;
-
- nremain = nbytes;
-
- while (nremain > 0) {
- if (SSL_want_write(THREADSSL)) {
- if ((SSL_read(THREADSSL, junk, 0)) < 1) {
- lprintf(9, "SSL_read in client_write: %s\n",
- ERR_reason_error_string(ERR_get_error()));
- }
- }
- retval = SSL_write(THREADSSL, &buf[nbytes - nremain], nremain);
- if (retval < 1) {
- long errval;
-
- errval = SSL_get_error(THREADSSL, retval);
- if (errval == SSL_ERROR_WANT_READ ||
- errval == SSL_ERROR_WANT_WRITE) {
- sleep(1);
- continue;
- }
- lprintf(9, "SSL_write got error %ld, ret %d\n", errval, retval);
- if (retval == -1) {
- lprintf(9, "errno is %d\n", errno);
- }
- endtls();
- return;
- }
- nremain -= retval;
- }
-}
-
-
-/**
- * \brief read data from the encrypted layer.
- * \param buf charbuffer to read to
- * \param bytes how many
- * \param timeout how long should we wait?
- * \returns what???
- */
-int client_read_ssl(char *buf, int bytes, int timeout)
-{
-#if 0
- fd_set rfds;
- struct timeval tv;
- int retval;
- int s;
-#endif
- int len, rlen;
- char junk[1];
-
- if (THREADSSL == NULL) return(0);
-
- len = 0;
- while (len < bytes) {
-#if 0
- /**
- * This code is disabled because we don't need it when
- * using blocking reads (which we are). -IO
- */
- FD_ZERO(&rfds);
- s = BIO_get_fd(THREADSSL->rbio, NULL);
- FD_SET(s, &rfds);
- tv.tv_sec = timeout;
- tv.tv_usec = 0;
-
- retval = select(s + 1, &rfds, NULL, NULL, &tv);
-
- if (FD_ISSET(s, &rfds) == 0) {
- return (0);
- }
-
-#endif
- if (SSL_want_read(THREADSSL)) {
- if ((SSL_write(THREADSSL, junk, 0)) < 1) {
- lprintf(9, "SSL_write in client_read: %s\n", ERR_reason_error_string(ERR_get_error()));
- }
- }
- rlen = SSL_read(THREADSSL, &buf[len], bytes - len);
- if (rlen < 1) {
- long errval;
-
- errval = SSL_get_error(THREADSSL, rlen);
- if (errval == SSL_ERROR_WANT_READ ||
- errval == SSL_ERROR_WANT_WRITE) {
- sleep(1);
- continue;
- }
- lprintf(9, "SSL_read got error %ld\n", errval);
- endtls();
- return (0);
- }
- len += rlen;
- }
- return (1);
-}
-
-
-#endif /* HAVE_OPENSSL */
-/*@}*/
+++ /dev/null
-/*
- * ok, hacky, but gets us nice groups. so we define sub parts to join from other
- * files here. NO CODE IN HERE! This is comment shouldn't appear in doxygen.
- * we have:
- * CitadelConfig; WebcitDisplayItems; WebcitHttpServer; WebcitHttpServerGDav;
- * ClientPower; Calendaring; MenuInfrastructure; CitadelCommunitacion;
- * VCards
- * WebcitHttpServerRSS; tools;
- */
-
-
-/**
- * \defgroup CitadelConfig Configuration Mechanisms
- * \brief Functions about configuring citadel / webcit
- */
-
-/*@{*/
-/*@}*/
-
-/**
- * \defgroup tools Utility Functions
- * \brief Functions that aren't related to webcit topics
- */
-
-/*@{*/
-/*@}*/
-
-
-/**
- * \defgroup WebcitDisplayItems Display some mime types through webcit
- * \brief Functions that format mime types into HTML to the user
- */
-
-/*@{*/
-/*@}*/
-
-/**
- * \defgroup WebcitHttpServer the Webserver part
- * \brief Functions that run the HTTP-Deamon
- */
-
-/*@{*/
-/*@}*/
-
-/**
- * \defgroup WebcitHttpServerGDav Groupdav Mechanisms
- * \ingroup WebcitHttpServer
- * \brief Functions that handle groupdav requests
- */
-/*@{*/
-/*@}*/
-
-
-/**
- * \defgroup WebcitHttpServerRSS RSS Mechanisms
- * \ingroup WebcitHttpServer
- * \brief Functions that handle RSS requests
- */
-
-/*@{*/
-/*@}*/
-
-/**
- * \defgroup ClientPower Client powered Functionality
- * \brief Functions that spawn things on the webbrowser
- */
-
-/*@{*/
-/*@}*/
-
-/**
- * \defgroup Calendaring Calendaring background
- * \brief Functions that make the Business-logic of the calendaring items
- * \ingroup WebcitDisplayItems
- */
-
-/*@{*/
-/*@}*/
-
-/**
- * \defgroup VCards showing / editing VCards
- * \brief Functions that make the Business-logic of the vcard stuff
- * \ingroup WebcitDisplayItems
- */
-
-/*@{*/
-/*@}*/
-
-/**
- * \defgroup MenuInfrastructure Things that guide you through the webcit parts
- * \brief Functions that display menues, trees etc. to connect the parts of the
- * ui to a whole thing
- * \ingroup WebcitDisplayItems
- */
-
-/*@{*/
-/*@}*/
-
-/**
- * \defgroup CitadelCommunitacion Talk to the citadel server
- * \brief Functions that talk to the citadel server and process reviewed entities
- * \ingroup WebcitDisplayItems
- */
-
-/*@{*/
-/*@}*/
-
-
-
+++ /dev/null
-/*
- * $Id$
- */
-/**
- * \defgroup EditCal Editing calendar events.
- * \ingroup Calendaring
- */
-/*@{*/
-#include "webcit.h"
-#include "webserver.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
- */
-void display_edit_individual_event(icalcomponent *supplied_vevent, long msgnum) {
- icalcomponent *vevent;
- icalproperty *p;
- icalvalue *v;
- struct icaltimetype t_start, t_end;
- time_t now;
- struct tm tm_now;
- int created_new_vevent = 0;
- icalproperty *organizer = NULL;
- char organizer_string[SIZ];
- icalproperty *attendee = NULL;
- char attendee_string[SIZ];
- char buf[SIZ];
- int organizer_is_me = 0;
- int i;
- int sequence = 0;
-
- now = time(NULL);
- strcpy(organizer_string, "");
- strcpy(attendee_string, "");
-
- if (supplied_vevent != NULL) {
- vevent = supplied_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
- * NULL returned by icalcomponent_get_first_component() will
- * tell the next iteration of this function to create a
- * new one.
- */
- if (icalcomponent_isa(vevent) == ICAL_VCALENDAR_COMPONENT) {
- display_edit_individual_event(
- icalcomponent_get_first_component(
- vevent, ICAL_VEVENT_COMPONENT
- ), msgnum
- );
- return;
- }
- }
- else {
- vevent = icalcomponent_new(ICAL_VEVENT_COMPONENT);
- created_new_vevent = 1;
- }
-
- /** Learn the sequence */
- p = icalcomponent_get_first_property(vevent, ICAL_SEQUENCE_PROPERTY);
- if (p != NULL) {
- sequence = icalproperty_get_sequence(p);
- }
-
- /** Begin output */
- output_headers(1, 1, 2, 0, 0, 0);
- wprintf("<div id=\"banner\">\n"
- "<TABLE WIDTH=100%% BORDER=0 BGCOLOR=\"#444455\"><TR><TD>"
- "<SPAN CLASS=\"titlebar\">");
- wprintf(_("Add or edit an event"));
- wprintf("</SPAN>"
- "</TD></TR></TABLE>\n"
- "</div>\n<div id=\"content\">\n"
- );
-
- wprintf("<script type=\"text/javascript\">"
- "function grey_all_day() { "
- "if (document.EventForm.alldayevent.checked) {"
- "document.EventForm.dtstart_hour.value='0';"
- "document.EventForm.dtstart_hour.disabled = true;"
- "document.EventForm.dtstart_minute.value='0';"
- "document.EventForm.dtstart_minute.disabled = true;"
- "document.EventForm.dtend_hour.value='0';"
- "document.EventForm.dtend_hour.disabled = true;"
- "document.EventForm.dtend_minute.value='0';"
- "document.EventForm.dtend_minute.disabled = true;"
- "document.EventForm.dtend_month.disabled = true;"
- "document.EventForm.dtend_day.disabled = true;"
- "document.EventForm.dtend_year.disabled = true;"
- "}"
- "else {"
- "document.EventForm.dtstart_hour.disabled = false;"
- "document.EventForm.dtstart_minute.disabled = false;"
- "document.EventForm.dtend_hour.disabled = false;"
- "document.EventForm.dtend_minute.disabled = false;"
- "document.EventForm.dtend_month.disabled = false;"
- "document.EventForm.dtend_day.disabled = false;"
- "document.EventForm.dtend_year.disabled = false;"
- "}"
- "}"
- "</script>\n"
- );
-
-
- wprintf("<div class=\"fix_scrollbar_bug\">"
- "<table border=0 width=100%% bgcolor=\"#ffffff\"><tr><td>\n");
-
- /************************************************************
- * Uncomment this to see the UID in calendar events for debugging
- wprintf("UID == ");
- p = icalcomponent_get_first_property(vevent, ICAL_UID_PROPERTY);
- if (p != NULL) {
- escputs((char *)icalproperty_get_comment(p));
- }
- wprintf("<br />\n");
- wprintf("SEQUENCE == %d<br />\n", sequence);
- *************************************************************/
-
- wprintf("<FORM NAME=\"EventForm\" METHOD=\"POST\" action=\"save_event\">\n");
-
- wprintf("<INPUT TYPE=\"hidden\" NAME=\"msgnum\" VALUE=\"%ld\">\n",
- msgnum);
- wprintf("<INPUT TYPE=\"hidden\" NAME=\"calview\" VALUE=\"%s\">\n",
- bstr("calview"));
- wprintf("<INPUT TYPE=\"hidden\" NAME=\"year\" VALUE=\"%s\">\n",
- bstr("year"));
- wprintf("<INPUT TYPE=\"hidden\" NAME=\"month\" VALUE=\"%s\">\n",
- bstr("month"));
- wprintf("<INPUT TYPE=\"hidden\" NAME=\"day\" VALUE=\"%s\">\n",
- bstr("day"));
-
- /** Put it in a borderless table so it lines up nicely */
- wprintf("<TABLE border=0 width=100%%>\n");
-
- wprintf("<TR><TD><B>");
- wprintf(_("Summary"));
- wprintf("</B></TD><TD>\n"
- "<INPUT TYPE=\"text\" NAME=\"summary\" "
- "MAXLENGTH=\"64\" SIZE=\"64\" VALUE=\"");
- p = icalcomponent_get_first_property(vevent, ICAL_SUMMARY_PROPERTY);
- if (p != NULL) {
- escputs((char *)icalproperty_get_comment(p));
- }
- wprintf("\"></TD></TR>\n");
-
- wprintf("<TR><TD><B>");
- wprintf(_("Location"));
- wprintf("</B></TD><TD>\n"
- "<INPUT TYPE=\"text\" NAME=\"location\" "
- "MAXLENGTH=\"64\" SIZE=\"64\" VALUE=\"");
- p = icalcomponent_get_first_property(vevent, ICAL_LOCATION_PROPERTY);
- if (p != NULL) {
- escputs((char *)icalproperty_get_comment(p));
- }
- wprintf("\"></TD></TR>\n");
-
- wprintf("<TR><TD><B>");
- wprintf(_("Start"));
- wprintf("</B></TD><TD>\n");
- p = icalcomponent_get_first_property(vevent, ICAL_DTSTART_PROPERTY);
- if (p != NULL) {
- t_start = icalproperty_get_dtstart(p);
- if (t_start.is_date) {
- t_start.hour = 0;
- t_start.minute = 0;
- t_start.second = 0;
- }
- }
- else {
- localtime_r(&now, &tm_now);
- if (strlen(bstr("year")) > 0) {
- tm_now.tm_year = atoi(bstr("year")) - 1900;
- tm_now.tm_mon = atoi(bstr("month")) - 1;
- tm_now.tm_mday = atoi(bstr("day"));
- }
- if (strlen(bstr("hour")) > 0) {
- tm_now.tm_hour = atoi(bstr("hour"));
- tm_now.tm_min = atoi(bstr("minute"));
- tm_now.tm_sec = 0;
- }
- else {
- tm_now.tm_hour = 9;
- tm_now.tm_min = 0;
- tm_now.tm_sec = 0;
- }
-
- t_start = icaltime_from_timet_with_zone(
- mktime(&tm_now),
- ((!strcasecmp(bstr("alldayevent"), "yes")) ? 1 : 0),
- icaltimezone_get_utc_timezone()
- );
- t_start.is_utc = 1;
-
- }
- display_icaltimetype_as_webform(&t_start, "dtstart");
-
- wprintf("<INPUT TYPE=\"checkbox\" NAME=\"alldayevent\" "
- "VALUE=\"yes\" onClick=\"grey_all_day();\""
- " %s >%s",
- (t_start.is_date ? "CHECKED" : "" ),
- _("All day event")
- );
-
- wprintf("</TD></TR>\n");
-
- /**
- * If this is an all-day-event, set the end time to be identical to
- * the start time (the hour/minute/second will be set to midnight).
- * Otherwise extract or create it.
- */
- wprintf("<TR><TD><B>");
- wprintf(_("End"));
- wprintf("</B></TD><TD>\n");
- if (t_start.is_date) {
- t_end = t_start;
- }
- else {
- p = icalcomponent_get_first_property(vevent,
- ICAL_DTEND_PROPERTY);
- if (p != NULL) {
- t_end = icalproperty_get_dtend(p);
- }
- else {
- /**
- * If this is not an all-day event and there is no
- * end time specified, make the default one hour
- * from the start time.
- */
- t_end = t_start;
- t_end.hour += 1;
- t_end.second = 0;
- t_end = icaltime_normalize(t_end);
- /* t_end = icaltime_from_timet(now, 0); */
- }
- }
- display_icaltimetype_as_webform(&t_end, "dtend");
- wprintf("</TD></TR>\n");
-
- wprintf("<TR><TD><B>");
- wprintf(_("Notes"));
- wprintf("</B></TD><TD>\n"
- "<TEXTAREA NAME=\"description\" wrap=soft "
- "ROWS=5 COLS=80 WIDTH=80>\n"
- );
- p = icalcomponent_get_first_property(vevent, ICAL_DESCRIPTION_PROPERTY);
- if (p != NULL) {
- escputs((char *)icalproperty_get_comment(p));
- }
- wprintf("</TEXTAREA></TD></TR>");
-
- /**
- * For a new event, the user creating the event should be the
- * organizer. Set this field accordingly.
- */
- if (icalcomponent_get_first_property(vevent, ICAL_ORGANIZER_PROPERTY)
- == NULL) {
- sprintf(organizer_string, "MAILTO:%s", WC->cs_inet_email);
- icalcomponent_add_property(vevent,
- icalproperty_new_organizer(organizer_string)
- );
- }
-
- /**
- * Determine who is the organizer of this event.
- * We need to determine "me" or "not me."
- */
- organizer = icalcomponent_get_first_property(vevent, ICAL_ORGANIZER_PROPERTY);
- if (organizer != NULL) {
- strcpy(organizer_string, icalproperty_get_organizer(organizer));
- if (!strncasecmp(organizer_string, "MAILTO:", 7)) {
- strcpy(organizer_string, &organizer_string[7]);
- striplt(organizer_string);
- serv_printf("ISME %s", organizer_string);
- serv_getln(buf, sizeof buf);
- if (buf[0] == '2') {
- organizer_is_me = 1;
- }
- }
- }
-
- wprintf("<TR><TD><B>");
- wprintf(_("Organizer"));
- wprintf("</B></TD><TD>");
- escputs(organizer_string);
- if (organizer_is_me) {
- wprintf(" <FONT SIZE=-1><I>");
- wprintf(_("(you are the organizer)"));
- wprintf("</I></FONT>\n");
- }
-
- /**
- * Transmit the organizer as a hidden field. We don't want the user
- * to be able to change it, but we do want it fed back to the server,
- * especially if this is a new event and there is no organizer already
- * in the calendar object.
- */
- wprintf("<INPUT TYPE=\"hidden\" NAME=\"organizer\" VALUE=\"");
- escputs(organizer_string);
- wprintf("\">");
-
- wprintf("</TD></TR>\n");
-
- /** Transparency */
- wprintf("<TR><TD><B>");
- wprintf(_("Show time as:"));
- wprintf("</B></TD><TD>");
-
- p = icalcomponent_get_first_property(vevent, ICAL_TRANSP_PROPERTY);
- if (p == NULL) {
- /** No transparency found. Default to opaque (busy). */
- p = icalproperty_new_transp(ICAL_TRANSP_OPAQUE);
- if (p != NULL) {
- icalcomponent_add_property(vevent, p);
- }
- }
- if (p != NULL) {
- v = icalproperty_get_value(p);
- }
- else {
- v = NULL;
- }
-
- wprintf("<INPUT TYPE=\"radio\" NAME=\"transp\" VALUE=\"transparent\"");
- if (v != NULL) if (icalvalue_get_transp(v) == ICAL_TRANSP_TRANSPARENT)
- wprintf(" CHECKED");
- wprintf(">");
- wprintf(_("Free"));
- wprintf(" ");
-
- wprintf("<INPUT TYPE=\"radio\" NAME=\"transp\" VALUE=\"opaque\"");
- if (v != NULL) if (icalvalue_get_transp(v) == ICAL_TRANSP_OPAQUE)
- wprintf(" CHECKED");
- wprintf(">");
- wprintf(_("Busy"));
-
- wprintf("</TD></TR>\n");
-
- /** Attendees */
- wprintf("<TR><TD><B>");
- wprintf(_("Attendees"));
- wprintf("</B><br />"
- "<FONT SIZE=-2>");
- wprintf(_("(One per line)"));
- wprintf("</FONT></TD><TD>"
- "<TEXTAREA %s NAME=\"attendees\" wrap=soft "
- "ROWS=3 COLS=80 WIDTH=80>\n",
- (organizer_is_me ? "" : "DISABLED ")
- );
- i = 0;
- for (attendee = icalcomponent_get_first_property(vevent, ICAL_ATTENDEE_PROPERTY);
- attendee != NULL;
- attendee = icalcomponent_get_next_property(vevent, ICAL_ATTENDEE_PROPERTY)) {
- strcpy(attendee_string, icalproperty_get_attendee(attendee));
- if (!strncasecmp(attendee_string, "MAILTO:", 7)) {
-
- /** screen name or email address */
- strcpy(attendee_string, &attendee_string[7]);
- striplt(attendee_string);
- if (i++) wprintf("\n");
- escputs(attendee_string);
- wprintf(" ");
-
- /** participant status */
- partstat_as_string(buf, attendee);
- escputs(buf);
- }
- }
- wprintf("</TEXTAREA></TD></TR>\n");
-
- /** Done with properties. */
- wprintf("</TABLE>\n<CENTER>"
- "<INPUT TYPE=\"submit\" NAME=\"save_button\" VALUE=\"%s\">"
- " "
- "<INPUT TYPE=\"submit\" NAME=\"delete_button\" VALUE=\"%s\">\n"
- " "
- "<INPUT TYPE=\"submit\" NAME=\"check_button\" "
- "VALUE=\"%s\">\n"
- " "
- "<INPUT TYPE=\"submit\" NAME=\"cancel_button\" VALUE=\"%s\">\n"
- "</CENTER>\n",
- _("Save"),
- _("Delete"),
- _("Check attendee availability"),
- _("Cancel")
- );
-
- wprintf("</FORM>\n");
-
- wprintf("</td></tr></table></div>\n");
- wprintf("<script type=\"text/javascript\">"
- "grey_all_day();"
- "</script>\n"
- );
- wDumpContent(1);
-
- if (created_new_vevent) {
- icalcomponent_free(vevent);
- }
-}
-
-/**
- * \brief Save an edited event
- * \param supplied_vevent the event to save
- * \param msgnum the index on the citserver
- */
-void save_individual_event(icalcomponent *supplied_vevent, long msgnum) {
- char buf[SIZ];
- icalproperty *prop;
- icalcomponent *vevent, *encaps;
- int created_new_vevent = 0;
- int all_day_event = 0;
- struct icaltimetype event_start, t;
- icalproperty *attendee = NULL;
- char attendee_string[SIZ];
- int i;
- int foundit;
- char form_attendees[SIZ];
- char organizer_string[SIZ];
- int sequence = 0;
- enum icalproperty_transp formtransp = ICAL_TRANSP_NONE;
-
- if (supplied_vevent != NULL) {
- vevent = supplied_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
- * NULL returned by icalcomponent_get_first_component() will
- * tell the next iteration of this function to create a
- * new one.
- */
- if (icalcomponent_isa(vevent) == ICAL_VCALENDAR_COMPONENT) {
- save_individual_event(
- icalcomponent_get_first_component(
- vevent, ICAL_VEVENT_COMPONENT
- ), msgnum
- );
- return;
- }
- }
- else {
- vevent = icalcomponent_new(ICAL_VEVENT_COMPONENT);
- created_new_vevent = 1;
- }
-
- if ( (strlen(bstr("save_button")) > 0)
- || (strlen(bstr("check_button")) > 0) ) {
-
- /** Replace values in the component with ones from the form */
-
- while (prop = icalcomponent_get_first_property(vevent,
- ICAL_SUMMARY_PROPERTY), prop != NULL) {
- icalcomponent_remove_property(vevent, prop);
- icalproperty_free(prop);
- }
- icalcomponent_add_property(vevent,
- icalproperty_new_summary(bstr("summary")));
-
- while (prop = icalcomponent_get_first_property(vevent,
- ICAL_LOCATION_PROPERTY), prop != NULL) {
- icalcomponent_remove_property(vevent, prop);
- icalproperty_free(prop);
- }
- icalcomponent_add_property(vevent,
- icalproperty_new_location(bstr("location")));
-
- while (prop = icalcomponent_get_first_property(vevent,
- ICAL_DESCRIPTION_PROPERTY), prop != NULL) {
- icalcomponent_remove_property(vevent, prop);
- icalproperty_free(prop);
- }
- icalcomponent_add_property(vevent,
- icalproperty_new_description(bstr("description")));
-
- while (prop = icalcomponent_get_first_property(vevent,
- ICAL_DTSTART_PROPERTY), prop != NULL) {
- icalcomponent_remove_property(vevent, prop);
- icalproperty_free(prop);
- }
-
- if (!strcmp(bstr("alldayevent"), "yes")) {
- all_day_event = 1;
- }
- else {
- all_day_event = 0;
- }
-
- if (all_day_event) {
- icaltime_from_webform_dateonly(&event_start, "dtstart");
- }
- else {
- 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) {
- icalproperty_set_value(prop,
- icalvalue_new_date(event_start)
- );
- }
-
- if (prop) icalcomponent_add_property(vevent, prop);
- else icalproperty_free(prop);
-
- while (prop = icalcomponent_get_first_property(vevent,
- ICAL_DTEND_PROPERTY), prop != NULL) {
- icalcomponent_remove_property(vevent, prop);
- icalproperty_free(prop);
- }
- while (prop = icalcomponent_get_first_property(vevent,
- ICAL_DURATION_PROPERTY), prop != NULL) {
- icalcomponent_remove_property(vevent, prop);
- icalproperty_free(prop);
- }
-
- if (all_day_event == 0) {
- icaltime_from_webform(&t, "dtend");
- icalcomponent_add_property(vevent,
- icalproperty_new_dtend(icaltime_normalize(t)
- )
- );
- }
-
- /** See if transparency is indicated */
- if (strlen(bstr("transp")) > 0) {
- if (!strcasecmp(bstr("transp"), "opaque")) {
- formtransp = ICAL_TRANSP_OPAQUE;
- }
- else if (!strcasecmp(bstr("transp"), "transparent")) {
- formtransp = ICAL_TRANSP_TRANSPARENT;
- }
-
- while (prop = icalcomponent_get_first_property(vevent, ICAL_TRANSP_PROPERTY),
- (prop != NULL)) {
- icalcomponent_remove_property(vevent, prop);
- icalproperty_free(prop);
- }
-
- lprintf(9, "adding new property...\n");
- icalcomponent_add_property(vevent, icalproperty_new_transp(formtransp));
- lprintf(9, "...added it.\n");
- }
-
- /** Give this event a UID if it doesn't have one. */
- lprintf(9, "Give this event a UID if it doesn't have one.\n");
- 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 */
- lprintf(9, "Increment the sequence ID\n");
- while (prop = icalcomponent_get_first_property(vevent,
- ICAL_SEQUENCE_PROPERTY), (prop != NULL) ) {
- i = icalproperty_get_sequence(prop);
- lprintf(9, "Sequence was %d\n", i);
- if (i > sequence) sequence = i;
- icalcomponent_remove_property(vevent, prop);
- icalproperty_free(prop);
- }
- ++sequence;
- lprintf(9, "New sequence is %d. Adding...\n", sequence);
- icalcomponent_add_property(vevent,
- icalproperty_new_sequence(sequence)
- );
-
- /**
- * Set the organizer, only if one does not already exist *and*
- * the form is supplying one
- */
- lprintf(9, "Setting the organizer...\n");
- strcpy(buf, bstr("organizer"));
- if ( (icalcomponent_get_first_property(vevent,
- ICAL_ORGANIZER_PROPERTY) == NULL)
- && (strlen(buf) > 0) ) {
-
- /** set new organizer */
- sprintf(organizer_string, "MAILTO:%s", buf);
- icalcomponent_add_property(vevent,
- icalproperty_new_organizer(organizer_string)
- );
-
- }
-
- /**
- * Add any new attendees listed in the web form
- */
- lprintf(9, "Add any new attendees\n");
-
- /* First, strip out the parenthesized partstats. */
- strcpy(form_attendees, bstr("attendees"));
- stripout(form_attendees, '(', ')');
-
- /** Now iterate! */
- for (i=0; i<num_tokens(form_attendees, '\n'); ++i) {
- extract_token(buf, form_attendees, i, '\n', sizeof buf);
- striplt(buf);
- if (strlen(buf) > 0) {
- lprintf(9, "Attendee: <%s>\n", buf);
- sprintf(attendee_string, "MAILTO:%s", buf);
- foundit = 0;
-
- for (attendee = icalcomponent_get_first_property(vevent, ICAL_ATTENDEE_PROPERTY); attendee != NULL; attendee = icalcomponent_get_next_property(vevent, ICAL_ATTENDEE_PROPERTY)) {
- if (!strcasecmp(attendee_string,
- icalproperty_get_attendee(attendee)))
- ++foundit;
- }
-
-
- if (foundit == 0) {
- icalcomponent_add_property(vevent,
- icalproperty_new_attendee(attendee_string)
- );
- }
- }
- }
-
- /**
- * Remove any attendees *not* listed in the web form
- */
-STARTOVER: lprintf(9, "Remove unlisted attendees\n");
- for (attendee = icalcomponent_get_first_property(vevent, ICAL_ATTENDEE_PROPERTY); attendee != NULL; attendee = icalcomponent_get_next_property(vevent, ICAL_ATTENDEE_PROPERTY)) {
- strcpy(attendee_string, icalproperty_get_attendee(attendee));
- if (!strncasecmp(attendee_string, "MAILTO:", 7)) {
- strcpy(attendee_string, &attendee_string[7]);
- striplt(attendee_string);
- foundit = 0;
- for (i=0; i<num_tokens(form_attendees, '\n'); ++i) {
- extract_token(buf, form_attendees, i, '\n', sizeof buf);
- striplt(buf);
- if (!strcasecmp(buf, attendee_string)) ++foundit;
- }
- if (foundit == 0) {
- icalcomponent_remove_property(vevent, attendee);
- icalproperty_free(attendee);
- goto STARTOVER;
- }
- }
- }
-
- /**
- * Encapsulate event into full VCALENDAR component. Clone it first,
- * for two reasons: one, it's easier to just free the whole thing
- * when we're done instead of unbundling, but more importantly, we
- * can't encapsulate something that may already be encapsulated
- * somewhere else.
- */
- lprintf(9, "Encapsulating into full VCALENDAR component\n");
- encaps = ical_encapsulate_subcomponent(icalcomponent_new_clone(vevent));
-
- /** If the user clicked 'Save' then save it to the server. */
- lprintf(9, "Serializing it for saving\n");
- if ( (encaps != NULL) && (strlen(bstr("save_button")) > 0) ) {
- serv_puts("ENT0 1|||4|||1|");
- serv_getln(buf, sizeof buf);
- if (buf[0] == '8') {
- serv_puts("Content-type: text/calendar");
- serv_puts("");
- serv_puts(icalcomponent_as_ical_string(encaps));
- serv_puts("000");
- }
- while (serv_getln(buf, sizeof buf), strcmp(buf, "000")) {
- lprintf(9, "ENT0 REPLY: %s\n", buf);
- }
- icalcomponent_free(encaps);
- }
-
- /** Or, check attendee availability if the user asked for that. */
- if ( (encaps != NULL) && (strlen(bstr("check_button")) > 0) ) {
-
- /** 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);
-
- icalcomponent_free(encaps);
- }
-
- }
-
- /**
- * If the user clicked 'Delete' then delete it.
- */
- lprintf(9, "Checking to see if we have to delete an old event\n");
- if ( (strlen(bstr("delete_button")) > 0) && (msgnum > 0L) ) {
- serv_printf("DELE %ld", atol(bstr("msgnum")));
- serv_getln(buf, sizeof buf);
- }
-
- if (created_new_vevent) {
- icalcomponent_free(vevent);
- }
-
- /** If this was a save or deelete, go back to the calendar view. */
- if (strlen(bstr("check_button")) == 0) {
- readloop("readfwd");
- }
-}
-
-
-#endif /* WEBCIT_WITH_CALENDAR_SERVICE */
-
-/*@}*/
+++ /dev/null
-/*
- * $Id$
- */
-/**
- * \defgroup AdminFloor Administrative screens for floor maintenance
- * \ingroup CitadelConfig
- */
-/*@{*/
-
-#include "webcit.h"
-#include "webserver.h"
-
-
-
-
-/**
- * \brief Display floor config
- * Display floor configuration. If prepend_html is not NULL, its contents
- * will be displayed at the top of the screen.
- * \param prepend_html pagetitle to prepend
- */
-void display_floorconfig(char *prepend_html)
-{
- char buf[SIZ];
-
- int floornum;
- char floorname[SIZ];
- int refcount;
-
- output_headers(1, 1, 2, 0, 0, 0);
- wprintf("<div id=\"banner\">\n"
- "<TABLE WIDTH=100%% BORDER=0 BGCOLOR=\"#444455\"><TR><TD>"
- "<SPAN CLASS=\"titlebar\">");
- wprintf(_("Add/change/delete floors"));
- wprintf("</SPAN>"
- "</TD></TR></TABLE>\n"
- "</div>\n<div id=\"content\">\n"
- );
-
- if (prepend_html != NULL) {
- wprintf("<br /><b><i>");
- client_write(prepend_html, strlen(prepend_html));
- wprintf("</i></b><br /><br />\n");
- }
-
- serv_printf("LFLR");
- serv_getln(buf, sizeof buf);
- if (buf[0] != '1') {
- wprintf("<TABLE WIDTH=100%% BORDER=0 BGCOLOR=\"#770000\"><TR><TD>");
- wprintf("<SPAN CLASS=\"titlebar\">");
- wprintf(_("Error"));
- wprintf("</SPAN>\n");
- wprintf("</TD></TR></TABLE>\n");
- wprintf("%s<br />\n", &buf[4]);
- wDumpContent(1);
- return;
- }
-
- wprintf("<div class=\"fix_scrollbar_bug\">"
- "<TABLE BORDER=1 WIDTH=100%% bgcolor=\"#ffffff\">\n"
- "<TR><TH>");
- wprintf(_("Floor number"));
- wprintf("</TH><TH>");
- wprintf(_("Floor name"));
- wprintf("</TH><TH>");
- wprintf(_("Number of rooms"));
- wprintf("</TH><TH>");
- wprintf(_("Floor CSS"));
- wprintf("</TH></TR>\n");
-
- while (serv_getln(buf, sizeof buf), strcmp(buf, "000")) {
- floornum = extract_int(buf, 0);
- extract_token(floorname, buf, 1, '|', sizeof floorname);
- refcount = extract_int(buf, 2);
-
- wprintf("<TR><TD><TABLE border=0><TR><TD>%d", floornum);
- if (refcount == 0) {
- wprintf("</TD><TD>"
- "<a href=\"delete_floor?floornum=%d\">"
- "<FONT SIZE=-1>", floornum);
- wprintf(_("(delete floor)"));
- wprintf("</A></FONT><br />");
- }
- wprintf("<FONT SIZE=-1>"
- "<a href=\"display_editfloorpic&"
- "which_floor=%d\">", floornum);
- wprintf(_("(edit graphic)"));
- wprintf("</A></TD></TR></TABLE>");
- wprintf("</TD>");
-
- wprintf("<TD>"
- "<FORM METHOD=\"POST\" action=\"rename_floor\">"
- "<INPUT TYPE=\"hidden\" NAME=\"floornum\" "
- "VALUE=\"%d\">"
- "<INPUT TYPE=\"text\" NAME=\"floorname\" "
- "VALUE=\"%s\" MAXLENGTH=\"250\">\n",
- floornum, floorname);
- wprintf("<INPUT TYPE=\"SUBMIT\" NAME=\"sc\" "
- "VALUE=\"%s\">"
- "</FORM></TD>", _("Change name"));
-
- wprintf("<TD>%d</TD>\n", refcount);
-
- wprintf("<TD>"
- "<FORM METHOD=\"POST\" action=\"set_floor_css\">"
- "<INPUT TYPE=\"hidden\" NAME=\"floornum\" "
- "VALUE=\"%d\">"
- "<INPUT TYPE=\"text\" NAME=\"floorcss\" "
- "VALUE=\"%s\" MAXLENGTH=\"250\">\n",
- floornum, floorname);
- wprintf("<INPUT TYPE=\"SUBMIT\" NAME=\"sc\" "
- "VALUE=\"%s\">"
- "</FORM></TD>", _("Change CSS"));
-
- wprintf("</TR>\n");
- }
-
- wprintf("<TR><TD> </TD>"
- "<TD><FORM METHOD=\"POST\" action=\"create_floor\">"
- "<INPUT TYPE=\"text\" NAME=\"floorname\" "
- "MAXLENGTH=\"250\">\n"
- "<INPUT TYPE=\"SUBMIT\" NAME=\"sc\" "
- "VALUE=\"%s\">"
- "</FORM></TD>"
- "<TD> </TD></TR>\n", _("Create new floor"));
-
- wprintf("</table></div>\n");
- wDumpContent(1);
-}
-
-
-/**
- * \brief delete the actual floor
- */
-void delete_floor(void) {
- int floornum;
- char buf[SIZ];
- char message[SIZ];
-
- floornum = atoi(bstr("floornum"));
-
- serv_printf("KFLR %d|1", floornum);
- serv_getln(buf, sizeof buf);
-
- if (buf[0] == '2') {
- sprintf(message, _("Floor has been deleted."));
- }
- else {
- sprintf(message, "%s", &buf[4]);
- }
-
- display_floorconfig(message);
-}
-
-/**
- * \brief tart creating a new floor
- */
-void create_floor(void) {
- char buf[SIZ];
- char message[SIZ];
- char floorname[SIZ];
-
- strcpy(floorname, bstr("floorname"));
-
- serv_printf("CFLR %s|1", floorname);
- serv_getln(buf, sizeof buf);
-
- if (buf[0] == '2') {
- sprintf(message, _("New floor has been created."));
- } else {
- sprintf(message, "%s", &buf[4]);
- }
-
- display_floorconfig(message);
-}
-
-/**
- * \brief rename this floor
- */
-void rename_floor(void) {
- int floornum;
- char buf[SIZ];
- char message[SIZ];
- char floorname[SIZ];
-
- floornum = atoi(bstr("floornum"));
- strcpy(floorname, bstr("floorname"));
-
- serv_printf("EFLR %d|%s", floornum, floorname);
- serv_getln(buf, sizeof buf);
-
- sprintf(message, "%s", &buf[4]);
-
- display_floorconfig(message);
-}
-
-
-/*@}*/
+++ /dev/null
-/*
- * $Id$
- */
-/**
- * \defgroup FormatDates Miscellaneous routines formating dates
- * \ingroup Calendaring
- */
-/*@{*/
-#include "webcit.h"
-#include "webserver.h"
-
-typedef unsigned char byte; /**< a byte. */
-
-#define FALSE 0 /**< no. */
-#define TRUE 1 /**< yes. */
-
-/**
- * \brief Wrapper around strftime() or strftime_l()
- * depending upon how our build is configured.
- *
- * \param s String target buffer
- * \param max Maximum size of string target buffer
- * \param format strftime() format
- * \param tm Input date/time
- */
-size_t wc_strftime(char *s, size_t max, const char *format, const struct tm *tm)
-{
-#ifdef ENABLE_NLS
- if (wc_locales[WC->selected_language] == NULL) {
- return strftime(s, max, format, tm);
- }
- else {
- return strftime_l(s, max, format, tm, wc_locales[WC->selected_language]);
- }
-#else
- return strftime(s, max, format, tm);
-#endif
-}
-
-
-/**
- * \brief Format a date/time stamp for output
- * \param buf the output buffer
- * \param thetime time to convert to string
- * \param brief do we want compact view?????
- */
-void fmt_date(char *buf, time_t thetime, int brief)
-{
- struct tm tm;
- struct tm today_tm;
- time_t today_timet;
- int hour;
- char calhourformat[16];
-
- get_preference("calhourformat", calhourformat, sizeof calhourformat);
-
- today_timet = time(NULL);
- localtime_r(&today_timet, &today_tm);
-
- localtime_r(&thetime, &tm);
- hour = tm.tm_hour;
- if (hour == 0)
- hour = 12;
- else if (hour > 12)
- hour = hour - 12;
-
- buf[0] = 0;
-
- if (brief) {
-
- /** If date == today, show only the time */
- if ((tm.tm_year == today_tm.tm_year)
- &&(tm.tm_mon == today_tm.tm_mon)
- &&(tm.tm_mday == today_tm.tm_mday)) {
- wc_strftime(buf, 32, "%l:%M%p", &tm);
- }
- /** Otherwise, for messages up to 6 months old, show the
- * month and day, and the time */
- else if (today_timet - thetime < 15552000) {
- wc_strftime(buf, 32, "%b %d %l:%M%p", &tm);
- }
- /** older than 6 months, show only the date */
- else {
- wc_strftime(buf, 32, "%b %d %Y", &tm);
- }
- }
- else {
- wc_strftime(buf, 32, "%c", &tm);
- }
-}
-
-
-/**
- * \brief Format TIME ONLY for output
- * \param buf the output buffer
- * \param thetime time to format into buf
- */
-void fmt_time(char *buf, time_t thetime)
-{
- struct tm *tm;
- int hour;
- char calhourformat[16];
-
- get_preference("calhourformat", calhourformat, sizeof calhourformat);
-
- buf[0] = 0;
- tm = localtime(&thetime);
- hour = tm->tm_hour;
- if (hour == 0)
- hour = 12;
- else if (hour > 12)
- hour = hour - 12;
-
- if (!strcasecmp(calhourformat, "24")) {
- sprintf(buf, "%2d:%02d",
- tm->tm_hour, tm->tm_min
- );
- }
- else {
- sprintf(buf, "%d:%02d%s",
- hour, tm->tm_min, ((tm->tm_hour > 12) ? "pm" : "am")
- );
- }
-}
-
-
-
-
-/**
- * \brief Break down the timestamp used in HTTP headers
- * Should read rfc1123 and rfc850 dates OK
- * \todo FIXME won't read asctime
- * Doesn't understand timezone, but we only should be using GMT/UTC anyway
- * \param buf time to parse
- * \return the time found in buf
- */
-time_t httpdate_to_timestamp(char *buf)
-{
- time_t t = 0;
- struct tm tt;
- char *c;
- char tz[256];
-
- /** Skip day of week, to number */
- for (c = buf; *c != ' '; c++)
- ;
- c++;
-
- /* Get day of month */
- tt.tm_mday = atoi(c);
- for (; *c != ' ' && *c != '-'; c++);
- c++;
-
- /** Get month */
- switch (*c) {
- case 'A': /** April, August */
- tt.tm_mon = (c[1] == 'p') ? 3 : 7;
- break;
- case 'D': /** December */
- tt.tm_mon = 11;
- break;
- case 'F': /** February */
- tt.tm_mon = 1;
- break;
- case 'M': /** March, May */
- tt.tm_mon = (c[2] == 'r') ? 2 : 4;
- break;
- case 'J': /** January, June, July */
- tt.tm_mon = (c[2] == 'n') ? ((c[1] == 'a') ? 0 : 5) : 6;
- break;
- case 'N': /** November */
- tt.tm_mon = 10;
- break;
- case 'O': /** October */
- tt.tm_mon = 9;
- break;
- case 'S': /** September */
- tt.tm_mon = 8;
- break;
- default:
- return 42;
- break; /** NOTREACHED */
- }
- c += 4;
-
- tt.tm_year = 0;
- /** Get year */
- tt.tm_year = atoi(c);
- for (; *c != ' '; c++);
- c++;
- if (tt.tm_year >= 1900)
- tt.tm_year -= 1900;
-
- /** Get hour */
- tt.tm_hour = atoi(c);
- for (; *c != ':'; c++);
- c++;
-
- /** Get minute */
- tt.tm_min = atoi(c);
- for (; *c != ':'; c++);
- c++;
-
- /** Get second */
- tt.tm_sec = atoi(c);
- for (; *c && *c != ' '; c++);
-
- /** Got everything; let's go */
- /** First, change to UTC */
- if (getenv("TZ"))
- sprintf(tz, "TZ=%s", getenv("TZ"));
- else
- strcpy(tz, "TZ=");
- putenv("TZ=UTC");
- tzset();
- t = mktime(&tt);
- putenv(tz);
- tzset();
- return t;
-}
-
-
-
-
-/*@}*/
+++ /dev/null
-/*
- * $Id
- */
-/**
- * \defgroup LocaleHeaderParser Parse the browser http locale headers and set the NLS stuff.
- * \ingroup WebcitHttpServer
- */
-/*@{*/
-#include "webcit.h"
-#include "webserver.h"
-
-#ifdef ENABLE_NLS
-
-#define NUM_LANGS 5 /**< how many different locales do we know? */
-#define SEARCH_LANG 20 /**< how many langs should we parse? */
-
-/** actual supported locales */
-char *AvailLang[NUM_LANGS] = {
- "C",
- "en_US",
- "de_DE",
- "it_IT",
- "en_GB"
-};
-
-locale_t wc_locales[NUM_LANGS]; /**< here we keep the parsed stuff */
-
-/** Keep information about one locale */
-typedef struct _lang_pref{
- char lang[16]; /**< the language locale string */
- char region[16]; /**< the region locale string */
- long priority; /**< which priority does it have */
- int availability; /**< do we know it? */
- int selectedlang; /**< is this the selected language? */
-} LangStruct;
-
-/* \brief parse browser locale header
- * seems as most browsers just do a one after coma value even if more than 10 locales are available. Sample strings:
- * opera:
- * Accept-Language: sq;q=1.0,de;q=0.9,as;q=0.8,ar;q=0.7,bn;q=0.6,zh-cn;q=0.5,kn;q=0.4,ch;q=0.3,fo;q=0.2,gn;q=0.1,ce;q=0.1,ie;q=0.1
- * Firefox
- * Accept-Language: 'de-de,en-us;q=0.7,en;q=0.3'
- * Accept-Language: de,en-ph;q=0.8,en-us;q=0.5,de-at;q=0.3
- * Accept-Language: de,en-us;q=0.9,it;q=0.9,de-de;q=0.8,en-ph;q=0.7,de-at;q=0.7,zh-cn;q=0.6,cy;q=0.5,ar-om;q=0.5,en-tt;q=0.4,xh;q=0.3,nl-be;q=0.3,cs;q=0.2,sv;q=0.1,tk;q=0.1
- * \param LocaleString the string from the browser http headers
- */
-
-void httplang_to_locale(char *LocaleString)
-{
- LangStruct wanted_locales[SEARCH_LANG];
- LangStruct *ls;
-
- int i = 0;
- int j = 0;
- size_t len = strlen(LocaleString);
- long prio;
- int av;
- int nBest;
- int nParts;
- char *search = (char *) malloc(len);
-
- memcpy(search, LocaleString, len);
- search[len] = '\0';
- nParts=num_tokens(search,',');
- for (i=0; ((i<nParts)&&(i<SEARCH_LANG)); i++)
- {
- char buf[16];
- char sbuf[16];
- char lbuf[16];
- int blen;
-
- ls=&wanted_locales[i];
-
- extract_token(&buf[0],search, i,',',16);
- /** we are searching, if this list item has something like ;q=n*/
- if (num_tokens(&buf[0],'=')>1) {
- int sbuflen, k;
- extract_token(&sbuf[0],&buf[0], 1,'=',16);
- sbuflen=strlen(&sbuf[0]);
- for (k=0; k<sbuflen; k++) if (sbuf[k]=='.') sbuf[k]='0';
- ls->priority=atol(&sbuf[0]);
- }
- else {
- ls->priority=1000;
- }
- /** get the locale part */
- extract_token(&sbuf[0],&buf[0],0,';',16);
- /** get the lang part, which should be allways there */
- extract_token(&ls->lang[0],&sbuf[0],0,'-',16);
- /** get the area code if any. */
- if (num_tokens(&sbuf[0],'-')>1) {
- extract_token(&ls->region[0],&sbuf[0],1,'-',16);
- }
- else { /** no ara code? use lang code */
- blen=strlen(&ls->lang[0]);
- memcpy(&ls->region[0], ls->lang,blen);
- ls->region[blen]='\0';
- } /** area codes are uppercase */
- blen=strlen(&ls->region[0]);
- for (j=0; j<blen; j++)
- {
- int chars=toupper(ls->region[j]);
- ls->region[j]=(char)chars;/** \todo ?! */
- }
- sprintf(&lbuf[0],"%s_%s",&ls->lang[0],&ls->region[0]);
-
- /** check if we have this lang */
- ls->availability=1;
- ls->selectedlang=-1;
- for (j=0; j<NUM_LANGS; j++) {
- int result;
- /** match against the LANG part */
- result=strcasecmp(&ls->lang[0], AvailLang[j]);
- if ((result<0)&&(result<ls->availability)){
- ls->availability=result;
- ls->selectedlang=j;
- }
- /** match against lang and locale */
- if (0==strcasecmp(&lbuf[0], AvailLang[j])){
- ls->availability=0;
- ls->selectedlang=j;
- j=NUM_LANGS;
- }
- }
- }
-
- prio=0;
- av=-1000;
- nBest=-1;
- for (i=0; ((i<nParts)&&(i<SEARCH_LANG)); i++)
- {
- ls=&wanted_locales[i];
- if ((ls->availability<=0)&&
- (av<ls->availability)&&
- (prio<ls->priority)&&
- (ls->selectedlang!=-1)){
- nBest=ls->selectedlang;
- av=ls->availability;
- prio=ls->priority;
- }
- }
- if (nBest==-1) /** fall back to C */
- nBest=0;
- WC->selected_language=nBest;
- lprintf(9, "language found: %s\n", AvailLang[WC->selected_language]);
- if (search != NULL) {
- free(search);
- }
-}
-
-/* TODO: we skip the language weightening so far. */
-/* Accept-Language: 'de-de,en-us;q=0.7,en;q=0.3' */
-/* Accept-Language: de,en-ph;q=0.8,en-us;q=0.5,de-at;q=0.3 */
-//void httplang_to_locale(char *LocaleString)
-//{
-// char selected_locale[16];
-// int i, j;
-// char lang[64];
-// int num_accept = 0;
-//
-// lprintf(9, "languageAccept: %s\n", LocaleString);
-//
-// strcpy(selected_locale, "C");
-// num_accept = num_tokens(LocaleString, ',');
-//
-// for (i=num_accept-1; i>=0; --i) {
-// extract_token(lang, LocaleString, i, ',', sizeof lang);
-//
-// /* Strip out the weights; we don't use them. Also convert
-// * hyphens to underscores.
-// */
-// for (j=0; j<strlen(lang); ++j) {
-// if (lang[j] == '-') lang[j] = '_';
-// if (lang[j] == ';') lang[j] = 0;
-// }
-//
-// for (j=0; j<NUM_LANGS; ++j) {
-// if (!strncasecmp(lang, AvailLang[j], strlen(lang))) {
-// strcpy(selected_locale, AvailLang[j]);
-// }
-// }
-// }
-//
-// lprintf(9, "language found: %s\n", selected_locale);
-// set_selected_language(selected_locale);
-//}
-
-
-/**
- * \brief show the language chooser on the login dialog
- * depending on the browser locale change the sequence of the
- * language chooser.
- */
-void offer_languages(void) {
- int i;
-
- wprintf("<select name=\"language\" size=\"1\">\n");
-
- for (i=0; i < NUM_LANGS; ++i) {
- wprintf("<option %s value=%s>%s</option>\n",
- ((WC->selected_language == i) ? "selected" : ""),
- AvailLang[i],
- AvailLang[i]
- );
- }
-
- wprintf("</select>\n");
-}
-
-/**
- * \brief Set the selected language for this session.
- * \param lang the locale to set.
- */
-void set_selected_language(char *lang) {
- int i;
-
- for (i=0; i<NUM_LANGS; ++i) {
- if (!strcasecmp(lang, AvailLang[i])) {
- WC->selected_language = i;
- }
- }
-}
-
-/**
- * \brief Activate the selected language for this session.
- */
-void go_selected_language(void) {
- if (WC->selected_language < 0) return;
- uselocale(wc_locales[WC->selected_language]); /** switch locales */
- textdomain(textdomain(NULL)); /** clear the cache */
-}
-
-/**
- * \brief Deactivate the selected language for this session.
- */
-void stop_selected_language(void) {
- uselocale(LC_GLOBAL_LOCALE); /** switch locales */
- textdomain(textdomain(NULL)); /** clear the cache */
-}
-
-
-/**
- * \brief Create a locale_t for each available language
- */
-void initialize_locales(void) {
- int i;
- locale_t Empty_Locale;
- char buf[32];
-
- /* create default locale */
- Empty_Locale = newlocale(LC_ALL_MASK, NULL, NULL);
-
- for (i = 0; i < NUM_LANGS; ++i) {
- if (i == 0) {
- sprintf(buf, "%s", AvailLang[i]); // locale 0 (C) is ascii, not utf-8
- }
- else {
- sprintf(buf, "%s.UTF8", AvailLang[i]);
- }
- wc_locales[i] = newlocale(
- (LC_MESSAGES_MASK|LC_TIME_MASK),
- buf,
- (((i > 0) && (wc_locales[0] != NULL)) ? wc_locales[0] : Empty_Locale)
- );
- if (wc_locales[i] == NULL) {
- lprintf(1, "Error configuring locale for %s: %s\n",
- buf,
- strerror(errno)
- );
- }
- else {
- lprintf(3, "Configured available locale: %s\n", buf);
- }
- }
-}
-
-
-#else /* ENABLE_NLS */
-/** \brief dummy for non NLS enabled systems */
-void offer_languages(void) {
- wprintf("English (US)");
-}
-
-/** \brief dummy for non NLS enabled systems */
-void set_selected_language(char *lang) {
-}
-
-/** \brief dummy for non NLS enabled systems */
-void go_selected_language(void) {
-}
-
-/** \brief dummy for non NLS enabled systems */
-void stop_selected_language(void) {
-}
-
-#endif /* ENABLE_NLS */
-
-
-/*@}*/
+++ /dev/null
-/*
- * $Id$
- *
- * Handles HTTP upload of graphics files into the system.
- * \ingroup WebcitHttpServer
- */
-
-#include "webcit.h"
-
-void display_graphics_upload(char *description, char *check_cmd, char *uplurl)
-{
- char buf[SIZ];
-
- serv_puts(check_cmd);
- serv_getln(buf, sizeof buf);
- if (buf[0] != '2') {
- strcpy(WC->ImportantMessage, &buf[4]);
- display_main_menu();
- return;
- }
- output_headers(1, 1, 0, 0, 0, 0);
-
- output_headers(1, 1, 2, 0, 0, 0);
- wprintf("<div id=\"banner\">\n"
- "<TABLE WIDTH=100%% BORDER=0 BGCOLOR=\"#444455\"><TR><TD>"
- "<SPAN CLASS=\"titlebar\">");
- wprintf(_("Image upload"));
- wprintf("</SPAN>"
- "</TD></TR></TABLE>\n"
- "</div>\n<div id=\"content\">\n"
- );
-
- wprintf("<div class=\"fix_scrollbar_bug\">"
- "<table border=0 width=100%% bgcolor=\"#ffffff\"><tr><td>\n");
-
- wprintf("<CENTER>\n");
-
- wprintf("<FORM ENCTYPE=\"multipart/form-data\" action=\"%s\" "
- "METHOD=\"POST\" NAME=\"graphicsupload\">\n", uplurl);
-
- wprintf("<INPUT TYPE=\"hidden\" NAME=\"which_room\" VALUE=\"");
- urlescputs(bstr("which_room"));
- wprintf("\">\n");
-
- wprintf(_("You can upload any image directly from your computer, "
- "as long as it is in GIF format (JPEG, PNG, etc. won't "
- "work)."));
- wprintf("<br /><br />\n");
-
- wprintf(_("Please select a file to upload:"));
- wprintf("<br /><br />\n");
- wprintf("<INPUT TYPE=\"FILE\" NAME=\"filename\" SIZE=\"35\">\n");
- wprintf("<br /><br />");
- wprintf("<INPUT TYPE=\"SUBMIT\" NAME=\"upload_button\" VALUE=\"%s\">\n", _("Upload"));
- wprintf(" ");
- wprintf("<INPUT TYPE=\"RESET\" VALUE=\"%s\">\n", _("Reset form"));
- wprintf(" ");
- wprintf("<INPUT TYPE=\"SUBMIT\" NAME=\"cancel_button\" VALUE=\"%s\">\n", _("Cancel"));
- wprintf("</FORM>\n");
- wprintf("</CENTER>\n");
- wprintf("</td></tr></table></div>\n");
- wDumpContent(1);
-}
-
-void do_graphics_upload(char *upl_cmd)
-{
- char buf[SIZ];
- int bytes_remaining;
- int pos = 0;
- int thisblock;
-
- if (strlen(bstr("cancel_button")) > 0) {
- strcpy(WC->ImportantMessage,
- _("Graphics upload has been cancelled."));
- display_main_menu();
- return;
- }
-
- if (WC->upload_length == 0) {
- strcpy(WC->ImportantMessage,
- _("You didn't upload a file."));
- display_main_menu();
- return;
- }
- serv_puts(upl_cmd);
- serv_getln(buf, sizeof buf);
- if (buf[0] != '2') {
- strcpy(WC->ImportantMessage, &buf[4]);
- display_main_menu();
- return;
- }
- bytes_remaining = WC->upload_length;
- while (bytes_remaining) {
- thisblock = ((bytes_remaining > 4096) ? 4096 : bytes_remaining);
- serv_printf("WRIT %d", thisblock);
- serv_getln(buf, sizeof buf);
- if (buf[0] != '7') {
- strcpy(WC->ImportantMessage, &buf[4]);
- serv_puts("UCLS 0");
- serv_getln(buf, sizeof buf);
- display_main_menu();
- return;
- }
- thisblock = extract_int(&buf[4], 0);
- serv_write(&WC->upload[pos], thisblock);
- pos = pos + thisblock;
- bytes_remaining = bytes_remaining - thisblock;
- }
-
- serv_puts("UCLS 1");
- serv_getln(buf, sizeof buf);
- if (buf[0] != 'x') {
- display_success(&buf[4]);
- return;
- }
-}
+++ /dev/null
-/* $Id$ */
-
-void groupdav_common_headers(void);
-void groupdav_main(struct httprequest *, char *, int, char *);
-void groupdav_get(char *);
-void groupdav_put(char *, char *, char *, char *, int);
-void groupdav_delete(char *, char *);
-void groupdav_propfind(char *, int, char *, char *);
-void groupdav_options(char *);
-long locate_message_by_uid(char *);
-void groupdav_folder_list(void);
-void euid_escapize(char *, char *);
-void euid_unescapize(char *, char *);
-void groupdav_identify_host(void);
+++ /dev/null
-/*
- * $Id$
- *
- * Handles GroupDAV DELETE requests.
- *
- */
-
-#include "webcit.h"
-#include "webserver.h"
-#include "groupdav.h"
-
-
-/*
- * The pathname is always going to be /groupdav/room_name/euid
- */
-void groupdav_delete(char *dav_pathname, char *dav_ifmatch) {
- char dav_roomname[SIZ];
- char dav_uid[SIZ];
- long dav_msgnum = (-1);
- char buf[SIZ];
- int n = 0;
-
- /* First, break off the "/groupdav/" prefix */
- remove_token(dav_pathname, 0, '/');
- remove_token(dav_pathname, 0, '/');
-
- /* Now extract the message euid */
- n = num_tokens(dav_pathname, '/');
- extract_token(dav_uid, dav_pathname, n-1, '/', sizeof dav_uid);
- remove_token(dav_pathname, n-1, '/');
-
- /* What's left is the room name. Remove trailing slashes. */
- if (dav_pathname[strlen(dav_pathname)-1] == '/') {
- dav_pathname[strlen(dav_pathname)-1] = 0;
- }
- strcpy(dav_roomname, dav_pathname);
-
- /* Go to the correct room. */
- if (strcasecmp(WC->wc_roomname, dav_roomname)) {
- gotoroom(dav_roomname);
- }
- if (strcasecmp(WC->wc_roomname, dav_roomname)) {
- wprintf("HTTP/1.1 404 not found\r\n");
- groupdav_common_headers();
- wprintf("Content-Length: 0\r\n\r\n");
- return;
- }
-
- dav_msgnum = locate_message_by_uid(dav_uid);
-
- /*
- * If no item exists with the requested uid ... simple error.
- */
- if (dav_msgnum < 0L) {
- wprintf("HTTP/1.1 404 Not Found\r\n");
- groupdav_common_headers();
- wprintf("Content-Length: 0\r\n\r\n");
- return;
- }
-
- /*
- * It's there ... check the ETag and make sure it matches
- * the message number.
- */
- if (strlen(dav_ifmatch) > 0) {
- if (atol(dav_ifmatch) != dav_msgnum) {
- wprintf("HTTP/1.1 412 Precondition Failed\r\n");
- groupdav_common_headers();
- wprintf("Content-Length: 0\r\n\r\n");
- return;
- }
- }
-
- /*
- * Ok, attempt to delete the item.
- */
- serv_printf("DELE %ld", dav_msgnum);
- serv_getln(buf, sizeof buf);
- if (buf[0] == '2') {
- wprintf("HTTP/1.1 204 No Content\r\n"); /* success */
- groupdav_common_headers();
- wprintf("Content-Length: 0\r\n\r\n");
- }
- else {
- wprintf("HTTP/1.1 403 Forbidden\r\n"); /* access denied */
- groupdav_common_headers();
- wprintf("Content-Length: 0\r\n\r\n");
- }
- return;
-}
+++ /dev/null
-/*
- * $Id$
- *
- * Handles GroupDAV GET requests.
- *
- */
-
-#include "webcit.h"
-#include "webserver.h"
-#include "groupdav.h"
-
-
-/*
- * Fetch the entire contents of the room as one big ics file.
- * This is for "webcal://" type access.
- */
-void groupdav_get_big_ics(void) {
- char buf[1024];
-
- serv_puts("ICAL getics");
- serv_getln(buf, sizeof buf);
- if (buf[0] != '1') {
- wprintf("HTTP/1.1 404 not found\r\n");
- groupdav_common_headers();
- wprintf(
- "Content-Type: text/plain\r\n"
- "\r\n"
- "%s\r\n",
- &buf[4]
- );
- return;
- }
-
- wprintf("HTTP/1.1 200 OK\r\n");
- groupdav_common_headers();
- wprintf("Content-type: text/calendar; charset=UTF-8\r\n");
- begin_burst();
- while (serv_getln(buf, sizeof buf), strcmp(buf, "000")) {
- wprintf("%s\r\n", buf);
- }
- end_burst();
-}
-
-
-/*
- * The pathname is always going to take one of two formats:
- * /groupdav/room_name/euid (GroupDAV)
- * /groupdav/room_name (webcal)
- */
-void groupdav_get(char *dav_pathname) {
- char dav_roomname[1024];
- char dav_uid[1024];
- long dav_msgnum = (-1);
- char buf[1024];
- int in_body = 0;
- int found_content_type = 0;
-
- if (num_tokens(dav_pathname, '/') < 3) {
- wprintf("HTTP/1.1 404 not found\r\n");
- groupdav_common_headers();
- wprintf(
- "Content-Type: text/plain\r\n"
- "\r\n"
- "The object you requested was not found.\r\n"
- );
- return;
- }
-
- extract_token(dav_roomname, dav_pathname, 2, '/', sizeof dav_roomname);
- extract_token(dav_uid, dav_pathname, 3, '/', sizeof dav_uid);
- if ((!strcasecmp(dav_uid, "ics")) || (!strcasecmp(dav_uid, "calendar.ics"))) {
- strcpy(dav_uid, "");
- }
-
- /* Go to the correct room. */
- if (strcasecmp(WC->wc_roomname, dav_roomname)) {
- gotoroom(dav_roomname);
- }
- if (strcasecmp(WC->wc_roomname, dav_roomname)) {
- wprintf("HTTP/1.1 404 not found\r\n");
- groupdav_common_headers();
- wprintf(
- "Content-Type: text/plain\r\n"
- "\r\n"
- "There is no folder called \"%s\" on this server.\r\n",
- dav_roomname
- );
- return;
- }
-
- /** GET on the collection itself returns an ICS of the entire collection.
- */
- if (!strcasecmp(dav_uid, "")) {
- groupdav_get_big_ics();
- return;
- }
-
- dav_msgnum = locate_message_by_uid(dav_uid);
- serv_printf("MSG2 %ld", dav_msgnum);
- serv_getln(buf, sizeof buf);
- if (buf[0] != '1') {
- wprintf("HTTP/1.1 404 not found\r\n");
- groupdav_common_headers();
- wprintf(
- "Content-Type: text/plain\r\n"
- "\r\n"
- "Object \"%s\" was not found in the \"%s\" folder.\r\n",
- dav_uid,
- dav_roomname
- );
- return;
- }
-
- wprintf("HTTP/1.1 200 OK\r\n");
- groupdav_common_headers();
- wprintf("etag: \"%ld\"\r\n", dav_msgnum);
- while (serv_getln(buf, sizeof buf), strcmp(buf, "000")) {
- if (in_body) {
- wprintf("%s\r\n", buf);
- }
- else if (!strncasecmp(buf, "Date: ", 6)) {
- wprintf("%s\r\n", buf);
- }
- else if (!strncasecmp(buf, "Content-type: ", 14)) {
- wprintf("%s", buf);
- if (bmstrcasestr(buf, "charset=")) {
- wprintf("%s\r\n", buf);
- }
- else {
- wprintf("%s;charset=UTF-8\r\n", buf);
- }
- found_content_type = 1;
- }
- else if ((strlen(buf) == 0) && (in_body == 0)) {
- if (!found_content_type) {
- wprintf("Content-type: text/plain\r\n");
- }
- in_body = 1;
- begin_burst();
- }
- }
- end_burst();
-}
+++ /dev/null
-/*
- * $Id$
- *
- * Entry point for GroupDAV functions
- *
- */
-
-#include "webcit.h"
-#include "webserver.h"
-#include "groupdav.h"
-
-
-/*
- * Output HTTP headers which are common to all requests.
- *
- * Please observe that we don't use the usual output_headers()
- * and wDumpContent() functions in the GroupDAV subsystem, so we
- * do our own header stuff here.
- *
- */
-void groupdav_common_headers(void) {
- wprintf(
- "Server: %s / %s\r\n"
- "Connection: close\r\n",
- SERVER, serv_info.serv_software
- );
-}
-
-
-
-/*
- * string conversion function
- */
-void euid_escapize(char *target, char *source) {
- int i;
- int target_length = 0;
-
- strcpy(target, "");
- for (i=0; i<strlen(source); ++i) {
- if ( (isalnum(source[i])) || (source[i]=='-') || (source[i]=='_') ) {
- target[target_length] = source[i];
- target[++target_length] = 0;
- }
- else {
- sprintf(&target[target_length], "=%02X", source[i]);
- target_length += 3;
- }
- }
-}
-
-/*
- * string conversion function
- */
-void euid_unescapize(char *target, char *source) {
- int a, b;
- char hex[3];
- int target_length = 0;
-
- strcpy(target, "");
-
- for (a = 0; a < strlen(source); ++a) {
- if (source[a] == '=') {
- hex[0] = source[a + 1];
- hex[1] = source[a + 2];
- hex[2] = 0;
- b = 0;
- sscanf(hex, "%02x", &b);
- target[target_length] = b;
- target[++target_length] = 0;
- a += 2;
- }
- else {
- target[target_length] = source[a];
- target[++target_length] = 0;
- }
- }
-}
-
-
-
-
-/*
- * Main entry point for GroupDAV requests
- */
-void groupdav_main(struct httprequest *req,
- char *dav_content_type,
- int dav_content_length,
- char *dav_content
-) {
- struct httprequest *rptr;
- char dav_method[256];
- char dav_pathname[256];
- char dav_ifmatch[256];
- int dav_depth;
- char *ds;
- int i;
-
- strcpy(dav_method, "");
- strcpy(dav_pathname, "");
- strcpy(dav_ifmatch, "");
- dav_depth = 0;
-
- for (rptr=req; rptr!=NULL; rptr=rptr->next) {
- if (!strncasecmp(rptr->line, "Host: ", 6)) {
- if (strlen(WC->http_host) == 0) {
- safestrncpy(WC->http_host, &rptr->line[6],
- sizeof WC->http_host);
- }
- }
- if (!strncasecmp(rptr->line, "If-Match: ", 10)) {
- safestrncpy(dav_ifmatch, &rptr->line[10],
- sizeof dav_ifmatch);
- }
- if (!strncasecmp(rptr->line, "Depth: ", 7)) {
- if (!strcasecmp(&rptr->line[7], "infinity")) {
- dav_depth = 32767;
- }
- else if (!strcmp(&rptr->line[7], "0")) {
- dav_depth = 0;
- }
- else if (!strcmp(&rptr->line[7], "1")) {
- dav_depth = 1;
- }
- }
- }
-
- if (!WC->logged_in) {
- wprintf("HTTP/1.1 401 Unauthorized\r\n");
- groupdav_common_headers();
- wprintf("WWW-Authenticate: Basic realm=\"%s\"\r\n",
- serv_info.serv_humannode);
- wprintf("Content-Length: 0\r\n\r\n");
- return;
- }
-
- extract_token(dav_method, req->line, 0, ' ', sizeof dav_method);
- extract_token(dav_pathname, req->line, 1, ' ', sizeof dav_pathname);
- unescape_input(dav_pathname);
-
- /* If the request does not begin with "/groupdav", prepend it. If
- * we happen to introduce a double-slash, that's ok; we'll strip it
- * in the next step.
- *
- * (THIS IS DISABLED BECAUSE WE ARE NOW TRYING TO DO REAL DAV.)
- *
- if (strncasecmp(dav_pathname, "/groupdav", 9)) {
- char buf[512];
- snprintf(buf, sizeof buf, "/groupdav/%s", dav_pathname);
- safestrncpy(dav_pathname, buf, sizeof dav_pathname);
- }
- *
- */
-
- /* Remove any stray double-slashes in pathname */
- while (ds=strstr(dav_pathname, "//"), ds != NULL) {
- strcpy(ds, ds+1);
- }
-
- /*
- * If there's an If-Match: header, strip out the quotes if present, and
- * then if all that's left is an asterisk, make it go away entirely.
- */
- if (strlen(dav_ifmatch) > 0) {
- striplt(dav_ifmatch);
- if (dav_ifmatch[0] == '\"') {
- strcpy(dav_ifmatch, &dav_ifmatch[1]);
- for (i=0; i<strlen(dav_ifmatch); ++i) {
- if (dav_ifmatch[i] == '\"') {
- dav_ifmatch[i] = 0;
- }
- }
- }
- if (!strcmp(dav_ifmatch, "*")) {
- strcpy(dav_ifmatch, "");
- }
- }
-
- /*
- * The OPTIONS method is not required by GroupDAV. This is an
- * experiment to determine what might be involved in supporting
- * other variants of DAV in the future.
- */
- if (!strcasecmp(dav_method, "OPTIONS")) {
- groupdav_options(dav_pathname);
- return;
- }
-
- /*
- * The PROPFIND method is basically used to list all objects in a
- * room, or to list all relevant rooms on the server.
- */
- if (!strcasecmp(dav_method, "PROPFIND")) {
- groupdav_propfind(dav_pathname, dav_depth,
- dav_content_type, dav_content);
- return;
- }
-
- /*
- * The GET method is used for fetching individual items.
- */
- if (!strcasecmp(dav_method, "GET")) {
- groupdav_get(dav_pathname);
- return;
- }
-
- /*
- * The PUT method is used to add or modify items.
- */
- if (!strcasecmp(dav_method, "PUT")) {
- groupdav_put(dav_pathname, dav_ifmatch,
- dav_content_type, dav_content,
- dav_content_length);
- return;
- }
-
- /*
- * The DELETE method kills, maims, and destroys.
- */
- if (!strcasecmp(dav_method, "DELETE")) {
- groupdav_delete(dav_pathname, dav_ifmatch);
- return;
- }
-
- /*
- * Couldn't find what we were looking for. Die in a car fire.
- */
- wprintf("HTTP/1.1 501 Method not implemented\r\n");
- groupdav_common_headers();
- wprintf("Content-Type: text/plain\r\n"
- "\r\n"
- "GroupDAV method \"%s\" is not implemented.\r\n",
- dav_method
- );
-}
-
-
-/*
- * Output our host prefix for globally absolute URL's.
- */
-void groupdav_identify_host(void) {
- if (strlen(WC->http_host) > 0) {
- wprintf("%s://%s",
- (is_https ? "https" : "http"),
- WC->http_host);
- }
-}
+++ /dev/null
-/*
- * $Id$
- *
- * Handles DAV OPTIONS requests (experimental -- not required by GroupDAV)
- *
- */
-
-#include "webcit.h"
-#include "webserver.h"
-#include "groupdav.h"
-
-/*
- * The pathname is always going to be /groupdav/room_name/msg_num
- */
-void groupdav_options(char *dav_pathname) {
- char dav_roomname[256];
- char dav_uid[256];
- long dav_msgnum = (-1);
- char datestring[256];
- time_t now;
-
- now = time(NULL);
- http_datestring(datestring, sizeof datestring, now);
-
- extract_token(dav_roomname, dav_pathname, 2, '/', sizeof dav_roomname);
- extract_token(dav_uid, dav_pathname, 3, '/', sizeof dav_uid);
-
- /*
- * If the room name is blank, the client is doing a top-level OPTIONS.
- */
- if (strlen(dav_roomname) == 0) {
- wprintf("HTTP/1.1 200 OK\r\n");
- groupdav_common_headers();
- wprintf("Date: %s\r\n", datestring);
- wprintf("DAV: 1\r\n");
- wprintf("Allow: OPTIONS, PROPFIND\r\n");
- wprintf("\r\n");
- return;
- }
-
- /* Go to the correct room. */
- if (strcasecmp(WC->wc_roomname, dav_roomname)) {
- gotoroom(dav_roomname);
- }
-
- if (strcasecmp(WC->wc_roomname, dav_roomname)) {
- wprintf("HTTP/1.1 404 not found\r\n");
- groupdav_common_headers();
- wprintf("Date: %s\r\n", datestring);
- wprintf(
- "Content-Type: text/plain\r\n"
- "\r\n"
- "There is no folder called \"%s\" on this server.\r\n",
- dav_roomname
- );
- return;
- }
-
- /* If dav_uid is non-empty, client is requesting an OPTIONS on
- * a specific item in the room.
- */
- if (strlen(dav_uid) > 0) {
-
- dav_msgnum = locate_message_by_uid(dav_uid);
- if (dav_msgnum < 0) {
- wprintf("HTTP/1.1 404 not found\r\n");
- groupdav_common_headers();
- wprintf(
- "Content-Type: text/plain\r\n"
- "\r\n"
- "Object \"%s\" was not found in the \"%s\" folder.\r\n",
- dav_uid,
- dav_roomname
- );
- return;
- }
-
- wprintf("HTTP/1.1 200 OK\r\n");
- groupdav_common_headers();
- wprintf("Date: %s\r\n", datestring);
- wprintf("DAV: 1\r\n");
- wprintf("Allow: OPTIONS, PROPFIND, GET, PUT, DELETE\r\n");
- wprintf("\r\n");
- return;
- }
-
- /*
- * We got to this point, which means that the client is requesting
- * an OPTIONS on the room itself.
- */
- wprintf("HTTP/1.1 200 OK\r\n");
- groupdav_common_headers();
- wprintf("Date: %s\r\n", datestring);
- wprintf("DAV: 1\r\n");
- wprintf("Allow: OPTIONS, PROPFIND, GET, PUT\r\n");
- wprintf("\r\n");
-}
+++ /dev/null
-/*
- * $Id$
- *
- * Handles GroupDAV PROPFIND requests.
- *
- * A few notes about our XML output:
- *
- * --> Yes, we are spewing tags directly instead of using an XML library.
- * If you would like to rewrite this using libxml2, code it up and submit
- * a patch. Whining will be summarily ignored.
- *
- * --> XML is deliberately output with no whitespace/newlines between tags.
- * This makes it difficult to read, but we have discovered clients which
- * crash when you try to pretty it up.
- *
- */
-
-#include "webcit.h"
-#include "webserver.h"
-#include "groupdav.h"
-
-/*
- * Given an encoded UID, translate that to an unencoded Citadel EUID and
- * then search for it in the current room. Return a message number or -1
- * if not found.
- *
- */
-long locate_message_by_uid(char *uid) {
- char buf[256];
- char decoded_uid[1024];
- long retval = (-1L);
-
- /* Decode the uid */
- euid_unescapize(decoded_uid, uid);
-
-/************** THE NEW WAY ***********************/
- serv_printf("EUID %s", decoded_uid);
- serv_getln(buf, sizeof buf);
- if (buf[0] == '2') {
- retval = atol(&buf[4]);
- }
-/***************************************************/
-
-/************** THE OLD WAY ***********************
- serv_puts("MSGS ALL|0|1");
- serv_getln(buf, sizeof buf);
- if (buf[0] == '8') {
- serv_printf("exti|%s", decoded_uid);
- serv_puts("000");
- while (serv_getln(buf, sizeof buf), strcmp(buf, "000")) {
- retval = atol(buf);
- }
- }
- ***************************************************/
-
- return(retval);
-}
-
-
-
-/*
- * List rooms (or "collections" in DAV terminology) which contain
- * interesting groupware objects.
- */
-void groupdav_collection_list(char *dav_pathname, int dav_depth)
-{
- char buf[256];
- char roomname[256];
- int view;
- char datestring[256];
- time_t now;
- time_t mtime;
- int is_groupware_collection = 0;
- int starting_point = 1; /**< 0 for /, 1 for /groupdav/ */
-
- if (!strcmp(dav_pathname, "/")) {
- starting_point = 0;
- }
- else if (!strcasecmp(dav_pathname, "/groupdav")) {
- starting_point = 1;
- }
- else if (!strcasecmp(dav_pathname, "/groupdav/")) {
- starting_point = 1;
- }
- else if ( (!strncasecmp(dav_pathname, "/groupdav/", 10)) && (strlen(dav_pathname) > 10) ) {
- starting_point = 2;
- }
-
- now = time(NULL);
- http_datestring(datestring, sizeof datestring, now);
-
- /**
- * Be rude. Completely ignore the XML request and simply send them
- * everything we know about. Let the client sort it out.
- */
- wprintf("HTTP/1.0 207 Multi-Status\r\n");
- groupdav_common_headers();
- wprintf("Date: %s\r\n", datestring);
- wprintf("Content-type: text/xml\r\n");
- wprintf("Content-encoding: identity\r\n");
-
- begin_burst();
-
- wprintf("<?xml version=\"1.0\" encoding=\"utf-8\"?>"
- "<multistatus xmlns=\"DAV:\" xmlns:G=\"http://groupdav.org/\">"
- );
-
- /**
- * If the client is requesting the root, show a root node.
- */
- if (starting_point == 0) {
- wprintf("<response>");
- wprintf("<href>");
- groupdav_identify_host();
- wprintf("/");
- wprintf("</href>");
- wprintf("<propstat>");
- wprintf("<status>HTTP/1.1 200 OK</status>");
- wprintf("<prop>");
- wprintf("<displayname>/</displayname>");
- wprintf("<resourcetype><collection/></resourcetype>");
- wprintf("<getlastmodified>");
- escputs(datestring);
- wprintf("</getlastmodified>");
- wprintf("</prop>");
- wprintf("</propstat>");
- wprintf("</response>");
- }
-
- /**
- * If the client is requesting "/groupdav", show a /groupdav subdirectory.
- */
- if ((starting_point + dav_depth) >= 1) {
- wprintf("<response>");
- wprintf("<href>");
- groupdav_identify_host();
- wprintf("/groupdav");
- wprintf("</href>");
- wprintf("<propstat>");
- wprintf("<status>HTTP/1.1 200 OK</status>");
- wprintf("<prop>");
- wprintf("<displayname>GroupDAV</displayname>");
- wprintf("<resourcetype><collection/></resourcetype>");
- wprintf("<getlastmodified>");
- escputs(datestring);
- wprintf("</getlastmodified>");
- wprintf("</prop>");
- wprintf("</propstat>");
- wprintf("</response>");
- }
-
- /**
- * Now go through the list and make it look like a DAV collection
- */
- serv_puts("LKRA");
- serv_getln(buf, sizeof buf);
- if (buf[0] == '1') while (serv_getln(buf, sizeof buf), strcmp(buf, "000")) {
-
- extract_token(roomname, buf, 0, '|', sizeof roomname);
- view = extract_int(buf, 7);
- mtime = extract_long(buf, 8);
- http_datestring(datestring, sizeof datestring, mtime);
-
- /*
- * For now, only list rooms that we know a GroupDAV client
- * might be interested in. In the future we may add
- * the rest.
- *
- * We determine the type of objects which are stored in each
- * room by looking at the *default* view for the room. This
- * allows, for example, a Calendar room to appear as a
- * GroupDAV calendar even if the user has switched it to a
- * Calendar List view.
- */
- if ((view == VIEW_CALENDAR) || (view == VIEW_TASKS) || (view == VIEW_ADDRESSBOOK) ) {
- is_groupware_collection = 1;
- }
- else {
- is_groupware_collection = 0;
- }
-
- if ( (is_groupware_collection) && ((starting_point + dav_depth) >= 2) ) {
- wprintf("<response>");
-
- wprintf("<href>");
- groupdav_identify_host();
- wprintf("/groupdav/");
- urlescputs(roomname);
- wprintf("/</href>");
-
- wprintf("<propstat>");
- wprintf("<status>HTTP/1.1 200 OK</status>");
- wprintf("<prop>");
- wprintf("<displayname>");
- escputs(roomname);
- wprintf("</displayname>");
- wprintf("<resourcetype><collection/>");
-
- switch(view) {
- case VIEW_CALENDAR:
- wprintf("<G:vevent-collection />");
- break;
- case VIEW_TASKS:
- wprintf("<G:vtodo-collection />");
- break;
- case VIEW_ADDRESSBOOK:
- wprintf("<G:vcard-collection />");
- break;
- }
-
- wprintf("</resourcetype>");
- wprintf("<getlastmodified>");
- escputs(datestring);
- wprintf("</getlastmodified>");
- wprintf("</prop>");
- wprintf("</propstat>");
- wprintf("</response>");
- }
- }
- wprintf("</multistatus>\n");
-
- end_burst();
-}
-
-
-
-/*
- * The pathname is always going to be /groupdav/room_name/msg_num
- */
-void groupdav_propfind(char *dav_pathname, int dav_depth, char *dav_content_type, char *dav_content) {
- char dav_roomname[256];
- char dav_uid[256];
- char msgnum[256];
- long dav_msgnum = (-1);
- char buf[256];
- char uid[256];
- char encoded_uid[256];
- long *msgs = NULL;
- int num_msgs = 0;
- int i;
- char datestring[256];
- time_t now;
-
- now = time(NULL);
- http_datestring(datestring, sizeof datestring, now);
-
- extract_token(dav_roomname, dav_pathname, 2, '/', sizeof dav_roomname);
- extract_token(dav_uid, dav_pathname, 3, '/', sizeof dav_uid);
-
- /*
- * If the room name is blank, the client is requesting a
- * folder list.
- */
- if (strlen(dav_roomname) == 0) {
- groupdav_collection_list(dav_pathname, dav_depth);
- return;
- }
-
- /* Go to the correct room. */
- if (strcasecmp(WC->wc_roomname, dav_roomname)) {
- gotoroom(dav_roomname);
- }
- if (strcasecmp(WC->wc_roomname, dav_roomname)) {
- wprintf("HTTP/1.1 404 not found\r\n");
- groupdav_common_headers();
- wprintf("Date: %s\r\n", datestring);
- wprintf(
- "Content-Type: text/plain\r\n"
- "\r\n"
- "There is no folder called \"%s\" on this server.\r\n",
- dav_roomname
- );
- return;
- }
-
- /* If dav_uid is non-empty, client is requesting a PROPFIND on
- * a specific item in the room. This is not valid GroupDAV, but
- * it is valid WebDAV.
- */
- if (strlen(dav_uid) > 0) {
-
- dav_msgnum = locate_message_by_uid(dav_uid);
- if (dav_msgnum < 0) {
- wprintf("HTTP/1.1 404 not found\r\n");
- groupdav_common_headers();
- wprintf(
- "Content-Type: text/plain\r\n"
- "\r\n"
- "Object \"%s\" was not found in the \"%s\" folder.\r\n",
- dav_uid,
- dav_roomname
- );
- return;
- }
-
- /* Be rude. Completely ignore the XML request and simply send them
- * everything we know about (which is going to simply be the ETag and
- * nothing else). Let the client-side parser sort it out.
- */
- wprintf("HTTP/1.0 207 Multi-Status\r\n");
- groupdav_common_headers();
- wprintf("Date: %s\r\n", datestring);
- wprintf("Content-type: text/xml\r\n");
- wprintf("Content-encoding: identity\r\n");
-
- begin_burst();
-
- wprintf("<?xml version=\"1.0\" encoding=\"utf-8\"?>"
- "<multistatus xmlns=\"DAV:\">"
- );
-
- wprintf("<response>");
-
- wprintf("<href>");
- groupdav_identify_host();
- wprintf("/groupdav/");
- urlescputs(WC->wc_roomname);
- euid_escapize(encoded_uid, dav_uid);
- wprintf("/%s", encoded_uid);
- wprintf("</href>");
- wprintf("<propstat>");
- wprintf("<status>HTTP/1.1 200 OK</status>");
- wprintf("<prop><getetag>\"%ld\"</getetag></prop>", dav_msgnum);
- wprintf("</propstat>");
-
- wprintf("</response>\n");
- wprintf("</multistatus>\n");
- end_burst();
- return;
- }
-
-
- /*
- * We got to this point, which means that the client is requesting
- * a 'collection' (i.e. a list of all items in the room).
- *
- * Be rude. Completely ignore the XML request and simply send them
- * everything we know about (which is going to simply be the ETag and
- * nothing else). Let the client-side parser sort it out.
- */
- wprintf("HTTP/1.0 207 Multi-Status\r\n");
- groupdav_common_headers();
- wprintf("Date: %s\r\n", datestring);
- wprintf("Content-type: text/xml\r\n");
- wprintf("Content-encoding: identity\r\n");
-
- begin_burst();
-
- wprintf("<?xml version=\"1.0\" encoding=\"utf-8\"?>"
- "<multistatus xmlns=\"DAV:\" xmlns:G=\"http://groupdav.org/\">"
- );
-
-
- /** Transmit the collection resource (FIXME check depth and starting point) */
- wprintf("<response>");
-
- wprintf("<href>");
- groupdav_identify_host();
- wprintf("/groupdav/");
- urlescputs(WC->wc_roomname);
- wprintf("</href>");
-
- wprintf("<propstat>");
- wprintf("<status>HTTP/1.1 200 OK</status>");
- wprintf("<prop>");
- wprintf("<displayname>");
- escputs(WC->wc_roomname);
- wprintf("</displayname>");
- wprintf("<resourcetype><collection/>");
-
- switch(WC->wc_default_view) {
- case VIEW_CALENDAR:
- wprintf("<G:vevent-collection />");
- break;
- case VIEW_TASKS:
- wprintf("<G:vtodo-collection />");
- break;
- case VIEW_ADDRESSBOOK:
- wprintf("<G:vcard-collection />");
- break;
- }
-
- wprintf("</resourcetype>");
- /* FIXME get the mtime
- wprintf("<getlastmodified>");
- escputs(datestring);
- wprintf("</getlastmodified>");
- */
- wprintf("</prop>");
- wprintf("</propstat>");
- wprintf("</response>");
-
- /** Transmit the collection listing (FIXME check depth and starting point) */
-
- serv_puts("MSGS ALL");
- serv_getln(buf, sizeof buf);
- if (buf[0] == '1') while (serv_getln(msgnum, sizeof msgnum), strcmp(msgnum, "000")) {
- msgs = realloc(msgs, ++num_msgs * sizeof(long));
- msgs[num_msgs-1] = atol(msgnum);
- }
-
- if (num_msgs > 0) for (i=0; i<num_msgs; ++i) {
-
- strcpy(uid, "");
- serv_printf("MSG0 %ld|3", msgs[i]);
- serv_getln(buf, sizeof buf);
- if (buf[0] == '1') while (serv_getln(buf, sizeof buf), strcmp(buf, "000")) {
- if (!strncasecmp(buf, "exti=", 5)) {
- strcpy(uid, &buf[5]);
- }
- }
-
- if (strlen(uid) > 0) {
- wprintf("<response>");
- wprintf("<href>");
- groupdav_identify_host();
- wprintf("/groupdav/");
- urlescputs(WC->wc_roomname);
- euid_escapize(encoded_uid, uid);
- wprintf("/%s", encoded_uid);
- wprintf("</href>");
- wprintf("<propstat>");
- wprintf("<status>HTTP/1.1 200 OK</status>");
- wprintf("<prop>");
- wprintf("<getetag>\"%ld\"</getetag>", msgs[i]);
- wprintf("</prop>");
- wprintf("</propstat>");
- wprintf("</response>");
- }
- }
-
- wprintf("</multistatus>\n");
- end_burst();
-
- if (msgs != NULL) {
- free(msgs);
- }
-}
+++ /dev/null
-/*
- * $Id$
- *
- * Handles GroupDAV PUT requests.
- *
- */
-
-#include "webcit.h"
-#include "webserver.h"
-#include "groupdav.h"
-
-
-/*
- * This function is for uploading an ENTIRE calendar, not just one
- * component. This would be for webcal:// 'publish' operations, not
- * for GroupDAV.
- */
-void groupdav_put_bigics(char *dav_content, int dav_content_length)
-{
- char buf[1024];
-
- serv_puts("ICAL putics");
- serv_getln(buf, sizeof buf);
- if (buf[0] != '4') {
- wprintf("HTTP/1.1 502 Bad Gateway\r\n");
- groupdav_common_headers();
- wprintf("Content-type: text/plain\r\n"
- "\r\n"
- "%s\r\n", &buf[4]
- );
- return;
- }
-
- serv_write(dav_content, dav_content_length);
- serv_printf("\n000");
-
- /* Report success and not much else. */
- wprintf("HTTP/1.1 204 No Content\r\n");
- lprintf(9, "HTTP/1.1 204 No Content\r\n");
- groupdav_common_headers();
- wprintf("Content-Length: 0\r\n\r\n");
-}
-
-
-
-/*
- * The pathname is always going to take one of two formats:
- * /groupdav/room_name/euid (GroupDAV)
- * /groupdav/room_name (webcal)
- */
-void groupdav_put(char *dav_pathname, char *dav_ifmatch,
- char *dav_content_type, char *dav_content,
- int dav_content_length
-) {
- char dav_roomname[1024];
- char dav_uid[1024];
- long new_msgnum = (-2L);
- long old_msgnum = (-1L);
- char buf[SIZ];
- int n = 0;
-
- if (num_tokens(dav_pathname, '/') < 3) {
- wprintf("HTTP/1.1 404 not found\r\n");
- groupdav_common_headers();
- wprintf(
- "Content-Type: text/plain\r\n"
- "\r\n"
- "The object you requested was not found.\r\n"
- );
- return;
- }
-
- extract_token(dav_roomname, dav_pathname, 2, '/', sizeof dav_roomname);
- extract_token(dav_uid, dav_pathname, 3, '/', sizeof dav_uid);
- if ((!strcasecmp(dav_uid, "ics")) || (!strcasecmp(dav_uid, "calendar.ics"))) {
- strcpy(dav_uid, "");
- }
-
- /* Go to the correct room. */
- if (strcasecmp(WC->wc_roomname, dav_roomname)) {
- gotoroom(dav_roomname);
- }
- if (strcasecmp(WC->wc_roomname, dav_roomname)) {
- wprintf("HTTP/1.1 404 not found\r\n");
- groupdav_common_headers();
- wprintf(
- "Content-Type: text/plain\r\n"
- "\r\n"
- "There is no folder called \"%s\" on this server.\r\n",
- dav_roomname
- );
- return;
- }
-
- /*
- * If an HTTP If-Match: header is present, the client is attempting
- * to replace an existing item. We have to check to see if the
- * message number associated with the supplied uid matches what the
- * client is expecting. If not, the server probably contains a newer
- * version, so we fail...
- */
- if (strlen(dav_ifmatch) > 0) {
- lprintf(9, "dav_ifmatch: %s\n", dav_ifmatch);
- old_msgnum = locate_message_by_uid(dav_uid);
- lprintf(9, "old_msgnum: %ld\n", old_msgnum);
- if (atol(dav_ifmatch) != old_msgnum) {
- wprintf("HTTP/1.1 412 Precondition Failed\r\n");
- lprintf(9, "HTTP/1.1 412 Precondition Failed (ifmatch=%ld, old_msgnum=%ld)\r\n",
- atol(dav_ifmatch), old_msgnum);
- groupdav_common_headers();
- wprintf("Content-Length: 0\r\n\r\n");
- return;
- }
- }
-
- /** PUT on the collection itself uploads an ICS of the entire collection.
- */
- if (!strcasecmp(dav_uid, "")) {
- groupdav_put_bigics(dav_content, dav_content_length);
- return;
- }
-
- /*
- * We are cleared for upload! We use the new calling syntax for ENT0
- * which allows a confirmation to be sent back to us. That's how we
- * extract the message ID.
- */
- serv_puts("ENT0 1|||4|||1|");
- serv_getln(buf, sizeof buf);
- if (buf[0] != '8') {
- wprintf("HTTP/1.1 502 Bad Gateway\r\n");
- groupdav_common_headers();
- wprintf("Content-type: text/plain\r\n"
- "\r\n"
- "%s\r\n", &buf[4]
- );
- return;
- }
-
- /* Send the content to the Citadel server */
- serv_printf("Content-type: %s\n\n", dav_content_type);
- serv_puts(dav_content);
- serv_puts("\n000");
-
- /* Fetch the reply from the Citadel server */
- n = 0;
- strcpy(dav_uid, "");
- while (serv_getln(buf, sizeof buf), strcmp(buf, "000")) {
- switch(n++) {
- case 0: new_msgnum = atol(buf);
- break;
- case 1: lprintf(9, "new_msgnum=%ld (%s)\n", new_msgnum, buf);
- break;
- case 2: strcpy(dav_uid, buf);
- break;
- default:
- break;
- }
- }
-
- /* Tell the client what happened. */
-
- /* Citadel failed in some way? */
- if (new_msgnum < 0L) {
- wprintf("HTTP/1.1 502 Bad Gateway\r\n");
- groupdav_common_headers();
- wprintf("Content-type: text/plain\r\n"
- "\r\n"
- "new_msgnum is %ld\r\n"
- "\r\n", new_msgnum
- );
- return;
- }
-
- /* We created this item for the first time. */
- if (old_msgnum < 0L) {
- wprintf("HTTP/1.1 201 Created\r\n");
- lprintf(9, "HTTP/1.1 201 Created\r\n");
- groupdav_common_headers();
- wprintf("etag: \"%ld\"\r\n", new_msgnum);
- wprintf("Content-Length: 0\r\n");
- wprintf("Location: ");
- groupdav_identify_host();
- wprintf("/groupdav/");
- urlescputs(dav_roomname);
- wprintf("/%s\r\n", dav_uid);
- wprintf("\r\n");
- return;
- }
-
- /* We modified an existing item. */
- wprintf("HTTP/1.1 204 No Content\r\n");
- lprintf(9, "HTTP/1.1 204 No Content\r\n");
- groupdav_common_headers();
- wprintf("etag: \"%ld\"\r\n", new_msgnum);
- wprintf("Content-Length: 0\r\n\r\n");
-
- /* The item we replaced has probably already been deleted by
- * the Citadel server, but we'll do this anyway, just in case.
- */
- serv_printf("DELE %ld", old_msgnum);
- serv_getln(buf, sizeof buf);
-
- return;
-}
+++ /dev/null
-/*
- * $Id$
- */
-/**
- * \defgroup HTML2HTML Output an HTML message, modifying it slightly to make sure it plays nice
- * with the rest of our web framework.
- * \ingroup WebcitHttpServer
- */
-/*@{*/
-#include "webcit.h"
-#include "vcard.h"
-#include "webserver.h"
-
-
-/**
- * \brief Strip surrounding single or double quotes from a string.
- *
- * \param s String to be stripped.
- */
-void stripquotes(char *s)
-{
- int len;
-
- if (!s) return;
-
- len = strlen(s);
- if (len < 2) return;
-
- if ( ( (s[0] == '\"') && (s[len-1] == '\"') ) || ( (s[0] == '\'') && (s[len-1] == '\'') ) ) {
- s[len-1] = 0;
- strcpy(s, &s[1]);
- }
-}
-
-
-/**
- * \brief Check to see if a META tag has overridden the declared MIME character set.
- *
- * \param charset Character set name (left unchanged if we don't do anything)
- * \param meta_http_equiv Content of the "http-equiv" portion of the META tag
- * \param meta_content Content of the "content" portion of the META tag
- */
-void extract_charset_from_meta(char *charset, char *meta_http_equiv, char *meta_content)
-{
- char *ptr;
- char buf[64];
-
- if (!charset) return;
- if (!meta_http_equiv) return;
- if (!meta_content) return;
-
-
- if (strcasecmp(meta_http_equiv, "Content-type")) return;
-
- ptr = strchr(meta_content, ';');
- if (!ptr) return;
-
- safestrncpy(buf, ++ptr, sizeof buf);
- striplt(buf);
- if (!strncasecmp(buf, "charset=", 8)) {
- strcpy(charset, &buf[8]);
- }
-}
-
-
-
-/**
- * \brief Sanitize and enhance an HTML message for display.
- * Also convert weird character sets to UTF-8 if necessary.
- *
- * \param supplied_charset the input charset as declared in the MIME headers
- */
-void output_html(char *supplied_charset, int treat_as_wiki) {
- char buf[SIZ];
- char *msg;
- char *ptr;
- char *msgstart;
- char *msgend;
- char *converted_msg;
- int buffer_length = 1;
- int line_length = 0;
- int content_length = 0;
- int output_length = 0;
- char new_window[SIZ];
- int brak = 0;
- int alevel = 0;
- int i;
- &n