* Create the Calendar> and Tasks> rooms at login time, and set their default
[citadel.git] / citadel / serv_calendar.c
1 /* 
2  * $Id$ 
3  *
4  * This module implements iCalendar object processing and the 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 /*
46  * We don't know if the calendar room exists so we just create it at login
47  */
48 void ical_create_room(void)
49 {
50         struct quickroom qr;
51         struct visit vbuf;
52
53         /* Create the calendar room if it doesn't already exist */
54         create_room(USERCALENDARROOM, 4, "", 0, 1, 0);
55
56         /* Set expiration policy to manual; otherwise objects will be lost! */
57         if (lgetroom(&qr, USERCALENDARROOM)) {
58                 lprintf(3, "Couldn't get the user calendar room!\n");
59                 return;
60         }
61         qr.QRep.expire_mode = EXPIRE_MANUAL;
62         lputroom(&qr);
63
64         /* Set the view to a calendar view */
65         CtdlGetRelationship(&vbuf, &CC->usersupp, &qr);
66         vbuf.v_view = 3;        /* 3 = calendar */
67         CtdlSetRelationship(&vbuf, &CC->usersupp, &qr);
68
69         /* Create the tasks list room if it doesn't already exist */
70         create_room(USERTASKSROOM, 4, "", 0, 1, 0);
71
72         /* Set expiration policy to manual; otherwise objects will be lost! */
73         if (lgetroom(&qr, USERTASKSROOM)) {
74                 lprintf(3, "Couldn't get the user calendar room!\n");
75                 return;
76         }
77         qr.QRep.expire_mode = EXPIRE_MANUAL;
78         lputroom(&qr);
79
80         /* Set the view to a task list view */
81         CtdlGetRelationship(&vbuf, &CC->usersupp, &qr);
82         vbuf.v_view = 4;        /* 4 = tasks */
83         CtdlSetRelationship(&vbuf, &CC->usersupp, &qr);
84
85         return;
86 }
87
88
89 /* See if we need to prevent the object from being saved */
90 int ical_obj_beforesave(struct CtdlMessage *msg)
91 {
92         char roomname[ROOMNAMELEN];
93         char *p;
94         int a;
95         
96         /*
97          * Only messages with content-type text/calendar or text/x-calendar
98          * may be saved to Calendar>.  If the message is bound for
99          * Calendar> but doesn't have this content-type, throw an error
100          * so that the message may not be posted.
101          */
102
103         /* First determine if this is our room */
104         MailboxName(roomname, sizeof roomname, &CC->usersupp, USERCALENDARROOM);
105         if (strncmp(roomname, msg->cm_fields['O'], ROOMNAMELEN))
106                 return 0;       /* It's not us... */
107
108         /* Then determine content-type of the message */
109         
110         /* It must be an RFC822 message! */
111         /* FIXME: Not handling MIME multipart messages; implement with IMIP */
112         if (msg->cm_format_type != 4)
113                 return 1;       /* You tried to save a non-RFC822 message! */
114         
115         /* Find the Content-Type: header */
116         p = msg->cm_fields['M'];
117         a = strlen(p);
118         while (--a > 0) {
119                 if (!strncasecmp(p, "Content-Type: ", 14)) {    /* Found it */
120                         if (!strncasecmp(p + 14, "text/x-calendar", 15) ||
121                             !strncasecmp(p + 14, "text/calendar", 13))
122                                 return 0;
123                         else
124                                 return 1;
125                 }
126                 p++;
127         }
128         
129         /* Oops!  No Content-Type in this message!  How'd that happen? */
130         lprintf(7, "RFC822 message with no Content-Type header!\n");
131         return 1;
132 }
133
134
135
136 /* Register this module with the Citadel server. */
137 char *Dynamic_Module_Init(void)
138 {
139         CtdlRegisterSessionHook(ical_create_room, EVT_LOGIN);
140         CtdlRegisterMessageHook(ical_obj_beforesave, EVT_BEFORESAVE);
141         CtdlRegisterProtoHook(cmd_ical, "ICAL", "Register iCalendar support");
142         return "$Id$";
143 }