]> err.no Git - scalable-opengroupware.org/blob - SoObjects/Appointments/SOGoCalendarComponent.m
git-svn-id: http://svn.opengroupware.org/SOGo/inverse/trunk@1025 d1b88da0-ebda-0310...
[scalable-opengroupware.org] / SoObjects / Appointments / SOGoCalendarComponent.m
1 /* SOGoCalendarComponent.m - this file is part of SOGo
2  *
3  * Copyright (C) 2006 Inverse groupe conseil
4  *
5  * Author: Wolfgang Sourdeau <wsourdeau@inverse.ca>
6  *
7  * This file is free software; you can redistribute it and/or modify
8  * it under the terms of the GNU General Public License as published by
9  * the Free Software Foundation; either version 2, or (at your option)
10  * any later version.
11  *
12  * This file is distributed in the hope that it will be useful,
13  * but WITHOUT ANY WARRANTY; without even the implied warranty of
14  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
15  * GNU General Public License for more details.
16  *
17  * You should have received a copy of the GNU General Public License
18  * along with this program; see the file COPYING.  If not, write to
19  * the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
20  * Boston, MA 02111-1307, USA.
21  */
22
23 #import <Foundation/NSString.h>
24
25 #import <NGCards/iCalCalendar.h>
26 #import <NGCards/iCalPerson.h>
27 #import <NGCards/iCalRepeatableEntityObject.h>
28 #import <NGMime/NGMime.h>
29 #import <NGMail/NGMail.h>
30 #import <NGMail/NGSendMail.h>
31
32 #import <SOGo/AgenorUserManager.h>
33 #import <SOGo/SOGoPermissions.h>
34
35 #import "common.h"
36
37 #import "SOGoAptMailNotification.h"
38 #import "SOGoCalendarComponent.h"
39
40 static NSString *mailTemplateDefaultLanguage = nil;
41 static BOOL sendEMailNotifications = NO;
42
43 @implementation SOGoCalendarComponent
44
45 + (void) initialize
46 {
47   NSUserDefaults      *ud;
48   static BOOL         didInit = NO;
49   
50   if (!didInit)
51     {
52       didInit = YES;
53   
54       ud = [NSUserDefaults standardUserDefaults];
55       mailTemplateDefaultLanguage = [[ud stringForKey:@"SOGoDefaultLanguage"]
56                                       retain];
57       if (!mailTemplateDefaultLanguage)
58         mailTemplateDefaultLanguage = @"French";
59
60       sendEMailNotifications
61         = [ud boolForKey: @"SOGoAppointmentSendEMailNotifications"];
62     }
63 }
64
65 - (id) init
66 {
67   if ((self = [super init]))
68     {
69       calendar = nil;
70     }
71
72   return self;
73 }
74
75 - (void) dealloc
76 {
77   if (calendar)
78     [calendar release];
79   [super dealloc];
80 }
81
82 - (NSString *) davContentType
83 {
84   return @"text/calendar";
85 }
86
87 - (NSString *) componentTag
88 {
89   [self subclassResponsibility: _cmd];
90
91   return nil;
92 }
93
94 - (iCalCalendar *) calendar
95 {
96   NSString *iCalString;
97
98   if (!calendar)
99     {
100       iCalString = [self contentAsString];
101       if (iCalString)
102         {
103           calendar = [iCalCalendar parseSingleFromSource: iCalString];
104           [calendar retain];
105         }
106     }
107
108   return calendar;
109 }
110
111 - (iCalRepeatableEntityObject *) component
112 {
113   return (iCalRepeatableEntityObject *)
114     [[self calendar]
115       firstChildWithTag: [self componentTag]];
116 }
117
118 /* raw saving */
119
120 - (NSException *) primarySaveContentString: (NSString *) _iCalString
121 {
122   return [super saveContentString: _iCalString];
123 }
124
125 - (NSException *) primaryDelete
126 {
127   return [super delete];
128 }
129
130 - (NSException *) deleteWithBaseSequence: (int) a
131 {
132   [self subclassResponsibility: _cmd];
133
134   return nil;
135 }
136
137 - (NSException *) delete
138 {
139   return [self deleteWithBaseSequence:0];
140 }
141
142 /* EMail Notifications */
143 - (NSString *) homePageURLForPerson: (iCalPerson *) _person
144 {
145   NSString *baseURL;
146   NSString *uid;
147   WOContext *ctx;
148   NSArray *traversalObjects;
149
150   /* generate URL from traversal stack */
151   ctx = [[WOApplication application] context];
152   traversalObjects = [ctx objectTraversalStack];
153   if ([traversalObjects count] > 0)
154     baseURL = [[traversalObjects objectAtIndex:0] baseURLInContext:ctx];
155   else
156     {
157       baseURL = @"http://localhost/";
158       [self warnWithFormat:@"Unable to create baseURL from context!"];
159     }
160   uid = [[AgenorUserManager sharedUserManager]
161           getUIDForEmail: [_person rfc822Email]];
162
163   return ((uid)
164           ? [NSString stringWithFormat:@"%@%@", baseURL, uid]
165           : nil);
166 }
167
168 - (BOOL) sendEMailNotifications
169 {
170   return sendEMailNotifications;
171 }
172
173 - (void) sendEMailUsingTemplateNamed: (NSString *) _pageName
174                         forOldObject: (iCalRepeatableEntityObject *) _oldObject
175                         andNewObject: (iCalRepeatableEntityObject *) _newObject
176                          toAttendees: (NSArray *) _attendees
177 {
178   NSString *pageName;
179   iCalPerson *organizer;
180   NSString *cn, *sender, *iCalString;
181   NGSendMail *sendmail;
182   WOApplication *app;
183   unsigned i, count;
184   iCalPerson *attendee;
185   NSString *recipient;
186   SOGoAptMailNotification *p;
187   NSString *subject, *text, *header;
188   NGMutableHashMap *headerMap;
189   NGMimeMessage *msg;
190   NGMimeBodyPart *bodyPart;
191   NGMimeMultipartBody *body;
192
193   if ([_attendees count])
194     {
195       /* sender */
196
197       organizer = [_newObject organizer];
198       cn = [organizer cnWithoutQuotes];
199       if (cn)
200         sender = [NSString stringWithFormat:@"%@ <%@>",
201                            cn,
202                            [organizer rfc822Email]];
203       else
204         sender = [organizer rfc822Email];
205
206       /* generate iCalString once */
207       iCalString = [[_newObject parent] versitString];
208   
209       /* get sendmail object */
210       sendmail = [NGSendMail sharedSendMail];
211
212       /* get WOApplication instance */
213       app = [WOApplication application];
214
215       /* generate dynamic message content */
216
217       count = [_attendees count];
218       for (i = 0; i < count; i++)
219         {
220           attendee = [_attendees objectAtIndex:i];
221
222           /* construct recipient */
223           cn = [attendee cn];
224           if (cn)
225             recipient = [NSString stringWithFormat: @"%@ <%@>",
226                                   cn,
227                                   [attendee rfc822Email]];
228           else
229             recipient = [attendee rfc822Email];
230
231           /* create page name */
232           // TODO: select user's default language?
233           pageName = [NSString stringWithFormat: @"SOGoAptMail%@%@",
234                                mailTemplateDefaultLanguage,
235                                _pageName];
236           /* construct message content */
237           p = [app pageWithName: pageName inContext: [WOContext context]];
238           [p setNewApt: _newObject];
239           [p setOldApt: _oldObject];
240           [p setHomePageURL: [self homePageURLForPerson: attendee]];
241           [p setViewTZ: [self userTimeZone: cn]];
242           subject = [p getSubject];
243           text = [p getBody];
244
245           /* construct message */
246           headerMap = [NGMutableHashMap hashMapWithCapacity: 5];
247           
248           /* NOTE: multipart/alternative seems like the correct choice but
249            * unfortunately Thunderbird doesn't offer the rich content alternative
250            * at all. Mail.app shows the rich content alternative _only_
251            * so we'll stick with multipart/mixed for the time being.
252            */
253           [headerMap setObject: @"multipart/mixed" forKey: @"content-type"];
254           [headerMap setObject: sender forKey: @"From"];
255           [headerMap setObject: recipient forKey: @"To"];
256           [headerMap setObject: [NSCalendarDate date] forKey: @"date"];
257           [headerMap setObject: subject forKey: @"Subject"];
258           msg = [NGMimeMessage messageWithHeader: headerMap];
259
260           /* multipart body */
261           body = [[NGMimeMultipartBody alloc] initWithPart: msg];
262     
263           /* text part */
264           headerMap = [NGMutableHashMap hashMapWithCapacity: 1];
265           [headerMap setObject: @"text/plain; charset=utf-8"
266                      forKey: @"content-type"];
267           bodyPart = [NGMimeBodyPart bodyPartWithHeader: headerMap];
268           [bodyPart setBody: [text dataUsingEncoding: NSUTF8StringEncoding]];
269
270           /* attach text part to multipart body */
271           [body addBodyPart: bodyPart];
272     
273           /* calendar part */
274           header = [NSString stringWithFormat: @"text/calendar; method=%@;"
275                              @" charset=utf-8",
276                              [(iCalCalendar *) [_newObject parent] method]];
277           headerMap = [NGMutableHashMap hashMapWithCapacity: 1];
278           [headerMap setObject:header forKey: @"content-type"];
279           bodyPart = [NGMimeBodyPart bodyPartWithHeader: headerMap];
280           [bodyPart setBody: [iCalString dataUsingEncoding: NSUTF8StringEncoding]];
281
282           /* attach calendar part to multipart body */
283           [body addBodyPart: bodyPart];
284     
285           /* attach multipart body to message */
286           [msg setBody: body];
287           [body release];
288
289           /* send the damn thing */
290           [sendmail sendMimePart: msg
291                     toRecipients: [NSArray arrayWithObject: [attendee rfc822Email]]
292                     sender: [organizer rfc822Email]];
293         }
294     }
295 }
296
297 - (NSString *) roleOfUser: (NSString *) login
298                 inContext: (WOContext *) context
299 {
300   AgenorUserManager *um;
301   iCalRepeatableEntityObject *component;
302   NSString *role, *email;
303
304   um = [AgenorUserManager sharedUserManager];
305   email = [um getEmailForUID: login];
306
307   component = [self component];
308   if ([component isOrganizer: email])
309     role = SOGoRole_Organizer;
310   else if ([component isParticipant: email])
311     role = SOGoRole_Participant;
312   else if ([[[self container] ownerInContext: nil] isEqualToString: login])
313     role = SoRole_Owner;
314   else
315     role = nil;
316
317   return role;
318 }
319
320 @end