f101f0b0b7054c44d37bcc3ba8cf82cc1c58c430
[citadel.git] / citadel / serv_calendar.c
1 /* 
2  * $Id$ 
3  *
4  * This module implements iCalendar object processing and the My Calendar>
5  * room on a Citadel/UX server.  It handles iCalendar objects using the
6  * iTIP protocol.  See RFCs 2445 and 2446.
7  *
8  */
9
10 #include "sysdep.h"
11 #include <unistd.h>
12 #include <sys/types.h>
13 #include <limits.h>
14 #include <stdio.h>
15 #include <string.h>
16 #ifdef HAVE_STRINGS_H
17 #include <strings.h>
18 #endif
19 #include "serv_calendar.h"
20 #include "citadel.h"
21 #include "server.h"
22 #include "citserver.h"
23 #include "sysdep_decls.h"
24 #include "support.h"
25 #include "config.h"
26 #include "dynloader.h"
27 #include "user_ops.h"
28 #include "room_ops.h"
29
30
31 /* Tell clients what level of support to expect */
32 void cmd_ical(char *argbuf)
33 {
34         /* argbuf is not used */
35         if (!(CC->logged_in)) {
36                 cprintf("%d Not logged in.\n", ERROR+NOT_LOGGED_IN);
37                 return;
38         }
39
40         cprintf("%d I support|ICAL\n", CIT_OK);
41         return;
42 }
43
44
45 /* We don't know if the calendar room exists so we just create it at login */
46 void ical_create_room(void)
47 {
48         struct quickroom qr;
49
50         /* Create the room if it doesn't already exist */
51         create_room(USERCALENDARROOM, 4, "", 0, 1, 0);
52         /* Set expiration policy to manual; otherwise objects will be lost! */
53         if (lgetroom(&qr, USERCALENDARROOM)) {
54                 lprintf(3, "Couldn't get the user calendar room!\n");
55                 return;
56         }
57         qr.QRep.expire_mode = EXPIRE_MANUAL;
58         lputroom(&qr);
59         lprintf(9, "Set user calendar room to manual expire\n");
60         return;
61 }
62
63
64 /* See if we need to prevent the object from being saved */
65 int ical_obj_beforesave(struct CtdlMessage *msg)
66 {
67         char roomname[ROOMNAMELEN];
68         char *p;
69         int a;
70         
71         /*
72          * Only messages with content-type text/calendar or text/x-calendar
73          * may be saved to My Calendar>.  If the message is bound for
74          * My Calendar> but doesn't have this content-type, throw an error
75          * so that the message may not be posted.
76          */
77
78         /* First determine if this is our room */
79         MailboxName(roomname, sizeof roomname, &CC->usersupp, USERCALENDARROOM);
80         if (strncmp(roomname, msg->cm_fields['O'], ROOMNAMELEN))
81                 return 0;       /* It's not us... */
82
83         /* Then determine content-type of the message */
84         
85         /* It must be an RFC822 message! */
86         /* FIXME: Not handling MIME multipart messages; implement with IMIP */
87         if (msg->cm_format_type != 4)
88                 return 1;       /* You tried to save a non-RFC822 message! */
89         
90         /* Find the Content-Type: header */
91         p = msg->cm_fields['M'];
92         a = strlen(p);
93         while (--a > 0) {
94                 if (!strncasecmp(p, "Content-Type: ", 14)) {    /* Found it */
95                         if (!strncasecmp(p + 14, "text/x-calendar", 15) ||
96                             !strncasecmp(p + 14, "text/calendar", 13))
97                                 return 0;
98                         else
99                                 return 1;
100                 }
101                 p++;
102         }
103         
104         /* Oops!  No Content-Type in this message!  How'd that happen? */
105         lprintf(7, "RFC822 message with no Content-Type header!\n");
106         return 1;
107 }
108
109
110
111 /* Register this module with the Citadel server. */
112 char *Dynamic_Module_Init(void)
113 {
114         CtdlRegisterSessionHook(ical_create_room, EVT_LOGIN);
115         CtdlRegisterMessageHook(ical_obj_beforesave, EVT_BEFORESAVE);
116         CtdlRegisterProtoHook(cmd_ical, "ICAL", "Register iCalendar support");
117         return "$Id$";
118 }