* serv_func.c: added utility function read_server_text()
[citadel.git] / webcit / availability.c
1 /*
2  * $Id$
3  *
4  * Check attendee availability for scheduling a meeting.
5  *
6  */
7
8 #include <ctype.h>
9 #include <stdlib.h>
10 #include <unistd.h>
11 #include <stdio.h>
12 #include <fcntl.h>
13 #include <signal.h>
14 #include <sys/types.h>
15 #include <sys/wait.h>
16 #include <sys/socket.h>
17 #include <limits.h>
18 #include <netinet/in.h>
19 #include <netdb.h>
20 #include <string.h>
21 #include <pwd.h>
22 #include <errno.h>
23 #include <stdarg.h>
24 #include <pthread.h>
25 #include <signal.h>
26 #include <time.h>
27 #include "webcit.h"
28 #include "webserver.h"
29
30
31 #ifdef WEBCIT_WITH_CALENDAR_SERVICE
32
33
34
35 /*
36  * Utility function to fetch a VFREEBUSY type of thing for
37  * any specified user.
38  */
39 icalcomponent *get_freebusy_for_user(char *who) {
40         char buf[SIZ];
41         char *serialized_fb = NULL;
42         icalcomponent *fb = NULL;
43
44         serv_printf("ICAL freebusy|%s", who);
45         serv_gets(buf);
46         if (buf[0] == '1') {
47                 serialized_fb = read_server_text();
48         }
49
50         if (serialized_fb == NULL) {
51                 return NULL;
52         }
53         
54         fb = icalcomponent_new_from_string(serialized_fb);
55         free(serialized_fb);
56         if (fb == NULL) {
57                 return NULL;
58         }
59
60         return fb;
61 }
62
63
64
65 /*
66  * Back end function for check_attendee_availability()
67  * This one checks an individual attendee against a supplied
68  * event start and end time.  All these fields have already been
69  * broken out.  The result is placed in 'annotation'.
70  */
71 void check_individual_attendee(char *attendee_string,
72                                 struct icaltimetype event_start,
73                                 struct icaltimetype event_end,
74                                 char *annotation) {
75
76         icalcomponent *fbc = NULL;
77         icalcomponent *fb = NULL;
78         icalproperty *thisfb = NULL;
79
80         /* Set to 'unknown' right from the beginning.  Unless we learn
81          * something else, that's what we'll go with.
82          */
83         strcpy(annotation, "availability unknown");
84
85         fbc = get_freebusy_for_user(attendee_string);
86         if (fbc == NULL) {
87                 return;
88         }
89
90         /* Make sure we're looking at a VFREEBUSY by itself.  What we're probably
91          * looking at initially is a VFREEBUSY encapsulated in a VCALENDAR.
92          */
93         if (icalcomponent_isa(fbc) == ICAL_VCALENDAR_COMPONENT) {
94                 fb = icalcomponent_get_first_component(fbc, ICAL_VFREEBUSY_COMPONENT);
95         }
96         else if (icalcomponent_isa(fbc) == ICAL_VFREEBUSY_COMPONENT) {
97                 fb = fbc;
98         }
99
100         /* Iterate through all FREEBUSY's looking for conflicts. */
101         if (fb != NULL) {
102
103                 strcpy(annotation, "free");
104
105                 for (thisfb = icalcomponent_get_first_property(fb, ICAL_FREEBUSY_PROPERTY);
106                     thisfb != NULL;
107                     thisfb = icalcomponent_get_next_property(fb, ICAL_FREEBUSY_PROPERTY) ) {
108         
109                         /* FIXME ... do the check */
110
111                 }
112         }
113
114         icalcomponent_free(fbc);
115 }
116
117
118
119 /*
120  * Check the availability of all attendees for an event (when possible)
121  * and annotate accordingly.
122  */
123 void check_attendee_availability(icalcomponent *vevent) {
124         icalproperty *attendee = NULL;
125         icalproperty *dtstart_p = NULL;
126         icalproperty *dtend_p = NULL;
127         struct icaltimetype dtstart_t;
128         struct icaltimetype dtend_t;
129         char attendee_string[SIZ];
130         char annotated_attendee_string[SIZ];
131         char annotation[SIZ];
132
133         if (vevent == NULL) {
134                 return;
135         }
136
137         /* If we're looking at a fully encapsulated VCALENDAR
138          * rather than a VEVENT component, attempt to use the first
139          * relevant VEVENT subcomponent.  If there is none, the
140          * NULL returned by icalcomponent_get_first_component() will
141          * tell the next iteration of this function to create a
142          * new one.
143          */
144         if (icalcomponent_isa(vevent) == ICAL_VCALENDAR_COMPONENT) {
145                 check_attendee_availability(
146                         icalcomponent_get_first_component(
147                                 vevent, ICAL_VEVENT_COMPONENT
148                         )
149                 );
150                 return;
151         }
152
153         /*
154          * Learn the start and end times.
155          */
156         dtstart_p = icalcomponent_get_first_property(vevent, ICAL_DTSTART_PROPERTY);
157         if (dtstart_p != NULL) dtstart_t = icalproperty_get_dtstart(dtstart_p);
158
159         dtend_p = icalcomponent_get_first_property(vevent, ICAL_DTEND_PROPERTY);
160         if (dtend_p != NULL) dtend_t = icalproperty_get_dtend(dtend_p);
161
162         /*
163          * Iterate through attendees.
164          */
165         for (attendee = icalcomponent_get_first_property(vevent, ICAL_ATTENDEE_PROPERTY);
166             attendee != NULL;
167             attendee = icalcomponent_get_next_property(vevent, ICAL_ATTENDEE_PROPERTY)) {
168
169                 strcpy(attendee_string, icalproperty_get_attendee(attendee));
170                 if (!strncasecmp(attendee_string, "MAILTO:", 7)) {
171
172                         /* screen name or email address */
173                         strcpy(attendee_string, &attendee_string[7]);
174                         striplt(attendee_string);
175
176                         check_individual_attendee(attendee_string,
177                                                 dtstart_t, dtend_t,
178                                                 annotation);
179
180                         /* Replace the attendee name with an annotated one. */
181                         snprintf(annotated_attendee_string, sizeof annotated_attendee_string,
182                                 "MAILTO:%s (%s)", attendee_string, annotation);
183                         icalproperty_set_attendee(attendee, annotated_attendee_string);
184
185                 }
186         }
187
188 }
189
190
191 #endif /* WEBCIT_WITH_CALENDAR_SERVICE */