e65ceda790d69cea45637a6d47e9cc73c14aa9e4
[citadel.git] / citadel / serv_ical.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_ical.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", 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);
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 /* User is reading a message */
65 int ical_obj_beforeread(struct CtdlMessage *msg)
66 {
67         return 0;
68 }
69
70
71 /* See if we need to prevent the object from being saved */
72 int ical_obj_beforesave(struct CtdlMessage *msg)
73 {
74         char roomname[ROOMNAMELEN];
75         char *p;
76         int a;
77         
78         /*
79          * Only messages with content-type text/calendar or text/x-calendar
80          * may be saved to My Calendar>.  If the message is bound for
81          * My Calendar> but doesn't have this content-type, throw an error
82          * so that the message may not be posted.
83          */
84
85         /* First determine if this is our room */
86         MailboxName(roomname, &CC->usersupp, USERCALENDARROOM);
87         if (strncmp(roomname, msg->cm_fields['O'], ROOMNAMELEN))
88                 return 0;       /* It's not us... */
89
90         /* Then determine content-type of the message */
91         
92         /* It must be an RFC822 message! */
93         /* FIXME: Not handling MIME multipart messages; implement with IMIP */
94         if (msg->cm_format_type != 4)
95                 return 1;       /* You tried to save a non-RFC822 message! */
96         
97         /* Find the Content-Type: header */
98         p = msg->cm_fields['M'];
99         a = strlen(p);
100         while (--a > 0) {
101                 if (!strncasecmp(p, "Content-Type: ", 14)) {    /* Found it */
102                         if (!strncasecmp(p + 14, "text/x-calendar", 15) ||
103                             !strncasecmp(p + 14, "text/calendar", 13))
104                                 return 0;
105                         else
106                                 return 1;
107                 }
108                 p++;
109         }
110         
111         /* Oops!  No Content-Type in this message!  How'd that happen? */
112         lprintf(7, "RFC822 message with no Content-Type header!\n");
113         return 1;
114 }
115
116
117 /* aftersave processing */
118 int ical_obj_aftersave(struct CtdlMessage *msg)
119 {
120         return 0;
121 }
122
123
124 /* Register this module with the Citadel server. */
125 char *Dynamic_Module_Init(void)
126 {
127         CtdlRegisterSessionHook(ical_create_room, EVT_LOGIN);
128         CtdlRegisterMessageHook(ical_obj_beforeread, EVT_BEFOREREAD);
129         CtdlRegisterMessageHook(ical_obj_beforesave, EVT_BEFORESAVE);
130         CtdlRegisterMessageHook(ical_obj_aftersave, EVT_AFTERSAVE);
131         CtdlRegisterProtoHook(cmd_ical, "ICAL", "Register iCalendar support");
132         return "$Id$";
133 }