]> err.no Git - scalable-opengroupware.org/blob - UI/MailPartViewers/UIxMailPartICalViewer.m
git-svn-id: http://svn.opengroupware.org/SOGo/inverse/trunk@1304 d1b88da0-ebda-0310...
[scalable-opengroupware.org] / UI / MailPartViewers / UIxMailPartICalViewer.m
1 /*
2   Copyright (C) 2004-2005 SKYRIX Software AG
3   
4   This file is part of OpenGroupware.org.
5
6   OGo is free software; you can redistribute it and/or modify it under
7   the terms of the GNU Lesser General Public License as published by the
8   Free Software Foundation; either version 2, or (at your option) any
9   later version.
10
11   OGo is distributed in the hope that it will be useful, but WITHOUT ANY
12   WARRANTY; without even the implied warranty of MERCHANTABILITY or
13   FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public
14   License for more details.
15
16   You should have received a copy of the GNU Lesser General Public
17   License along with OGo; see the file COPYING. If not, write to the
18   Free Software Foundation, 59 Temple Place - Suite 330, Boston, MA
19   02111-1307, USA.
20 */
21
22 /*
23   UIxMailPartICalViewer
24  
25   Show plain/calendar mail parts.
26 */
27
28 #import <NGObjWeb/WOResponse.h>
29
30 #import <NGExtensions/NSCalendarDate+misc.h>
31 #import <NGExtensions/NSObject+Logs.h>
32
33 #import <NGImap4/NGImap4EnvelopeAddress.h>
34
35 #import <NGCards/iCalCalendar.h>
36 #import <NGCards/iCalEvent.h>
37 #import <NGCards/iCalPerson.h>
38 #import <NGCards/iCalDateTime.h>
39
40 #import <SoObjects/SOGo/SOGoDateFormatter.h>
41 #import <SoObjects/SOGo/SOGoUser.h>
42 #import <SoObjects/Appointments/iCalEntityObject+SOGo.h>
43 #import <SoObjects/Appointments/SOGoAppointmentFolder.h>
44 #import <SoObjects/Appointments/SOGoAppointmentObject.h>
45 #import <SoObjects/Mailer/SOGoMailObject.h>
46 #import <SoObjects/Mailer/SOGoMailBodyPart.h>
47
48 #import "UIxMailPartICalViewer.h"
49
50 @implementation UIxMailPartICalViewer
51
52 - (void) dealloc
53 {
54   [storedEventObject release];
55   [storedEvent release];
56   [attendee release];
57   [item release];
58   [inCalendar release];
59   [inEvent release];
60   [dateFormatter release];
61   [super dealloc];
62 }
63
64 /* maintain caches */
65
66 - (void) resetPathCaches
67 {
68   [super resetPathCaches];
69   [inEvent release]; inEvent = nil;
70   [inCalendar release]; inCalendar = nil;
71   [storedEventObject release]; storedEventObject = nil;
72   [storedEvent release]; storedEvent = nil;
73  
74   /* not strictly path-related, but useless without it anyway: */
75   [attendee release]; attendee = nil;
76   [item release]; item = nil;
77 }
78
79 /* accessors */
80
81 - (iCalCalendar *) inCalendar
82 {
83   if (!inCalendar)
84     {
85       inCalendar
86         = [iCalCalendar parseSingleFromSource: [self flatContentAsString]];
87       [inCalendar retain];
88     }
89
90   return inCalendar;
91 }
92
93 - (BOOL) couldParseCalendar
94 {
95   return ([self inCalendar] != nil);
96 }
97
98 - (iCalEvent *) inEvent
99 {
100   NSArray *events;
101  
102   if (!inEvent)
103     {
104       events = [[self inCalendar] events];
105       if ([events count] > 0)
106         inEvent = [[events objectAtIndex:0] retain];
107     }
108
109   return inEvent;
110 }
111
112 /* formatters */
113
114 - (SOGoDateFormatter *) dateFormatter
115 {
116   if (!dateFormatter)
117     {
118       dateFormatter = [[context activeUser] dateFormatterInContext: context];
119       [dateFormatter retain];
120     }
121
122   return dateFormatter;
123 }
124
125 /* below is copied from UIxAppointmentView, can we avoid that? */
126
127 - (void) setAttendee: (id) _attendee
128 {
129   ASSIGN (attendee, _attendee);
130 }
131
132 - (id) attendee
133 {
134   return attendee;
135 }
136
137 - (NSString *) _personForDisplay: (iCalPerson *) person
138 {
139   NSString *fn, *email, *result;
140
141   fn = [person cnWithoutQuotes];
142   email = [person rfc822Email];
143   if ([fn length])
144     result = [NSString stringWithFormat: @"%@ <%@>",
145                        fn, email];
146   else
147     result = email;
148
149   return result;
150 }
151
152 - (NSString *) attendeeForDisplay
153 {
154   return [self _personForDisplay: attendee];
155 }
156
157 - (void) setItem: (id) _item
158 {
159   ASSIGN(item, _item);
160 }
161
162 - (id) item
163 {
164   return item;
165 }
166
167 - (NSCalendarDate *) startTime
168 {
169   NSCalendarDate *date;
170   NSTimeZone *timeZone;
171  
172   date = [[self authorativeEvent] startDate];
173   timeZone = [[context activeUser] timeZone];
174   [date setTimeZone: timeZone];
175
176   return date;
177 }
178
179 - (NSCalendarDate *) endTime
180 {
181   NSCalendarDate *date;
182   NSTimeZone *timeZone;
183  
184   date = [[self authorativeEvent] endDate];
185   timeZone = [[context activeUser] timeZone];
186   [date setTimeZone: timeZone];
187
188   return date;
189 }
190
191 - (BOOL) isEndDateOnSameDay
192 {
193   return [[self startTime] isDateOnSameDay:[self endTime]];
194 }
195
196 - (NSTimeInterval) duration
197 {
198   return [[self endTime] timeIntervalSinceDate:[self startTime]];
199 }
200
201 /* calendar folder support */
202
203 - (SOGoAppointmentFolder *) calendarFolder
204 {
205   /* return scheduling calendar of currently logged-in user */
206   SOGoUser *user;
207   id folder;
208
209   user = [context activeUser];
210   folder = [[user homeFolderInContext: context] lookupName: @"Calendar"
211                                                 inContext: context
212                                                 acquire: NO];
213
214   return [folder lookupName: @"personal" inContext: context acquire: NO];
215 }
216
217 - (SOGoAppointmentObject *) storedEventObject
218 {
219   /* lookup object in the users Calendar */
220   SOGoAppointmentFolder *calendar;
221   NSString *filename;
222  
223   if (!storedEventObject)
224     {
225       calendar = [self calendarFolder];
226       if ([calendar isKindOfClass: [NSException class]])
227         [self errorWithFormat:@"Did not find Calendar folder: %@", calendar];
228       else
229         {
230           filename = [calendar resourceNameForEventUID:[[self inEvent] uid]];
231           if (filename)
232             {
233               storedEventObject = [calendar lookupName: filename
234                                             inContext: [self context]
235                                             acquire: NO];
236               if ([storedEventObject isKindOfClass: [NSException class]])
237                 storedEventObject = nil;
238               else
239                 [storedEventObject retain];
240             }
241         }
242     }
243  
244   return storedEventObject;
245 }
246
247 - (BOOL) isEventStoredInCalendar
248 {
249   return ([self storedEventObject] != nil);
250 }
251
252 - (iCalEvent *) storedEvent
253 {
254   if (!storedEvent)
255     {
256       storedEvent = [[self storedEventObject] component: NO secure: NO];
257       [storedEvent retain];
258     }
259
260   return storedEvent;
261 }
262
263 /* organizer tracking */
264
265 - (NSString *) loggedInUserEMail
266 {
267   NSDictionary *identity;
268
269   identity = [[context activeUser] primaryIdentity];
270
271   return [identity objectForKey: @"email"];
272 }
273
274 - (iCalEvent *) authorativeEvent
275 {
276   iCalEvent *authorativeEvent;
277
278   [self storedEvent];
279   if (!storedEvent
280       || ([storedEvent compare: [self inEvent]] == NSOrderedAscending))
281     authorativeEvent = inEvent;
282   else
283     authorativeEvent = [self storedEvent];
284
285   return authorativeEvent;
286 }
287
288 - (BOOL) isLoggedInUserTheOrganizer
289 {
290   return [[self authorativeEvent] userIsOrganizer: [context activeUser]];
291 }
292
293 - (BOOL) isLoggedInUserAnAttendee
294 {
295   return [[self authorativeEvent] userIsParticipant: [context activeUser]];
296 }
297
298 /* derived fields */
299
300 - (NSString *) organizerDisplayName
301 {
302   iCalPerson *organizer;
303   NSString *value;
304
305   organizer = [[self authorativeEvent] organizer];
306   if (organizer)
307     value = [self _personForDisplay: organizer];
308   else
309     value = @"[todo: no organizer set, use 'from']";
310
311   return value;
312 }
313
314 /* replies */
315
316 - (NGImap4EnvelopeAddress *) replySenderAddress
317 {
318   /* 
319      The iMIP reply is the sender of the mail, the 'attendees' are NOT set to
320      the actual attendees. BUT the attendee field contains the reply-status!
321   */
322   id tmp;
323  
324   tmp = [[self clientObject] fromEnvelopeAddresses];
325   if ([tmp count] == 0) return nil;
326   return [tmp objectAtIndex:0];
327 }
328
329 - (NSString *) replySenderEMail
330 {
331   return [[self replySenderAddress] email];
332 }
333
334 - (NSString *) replySenderBaseEMail
335 {
336   return [[self replySenderAddress] baseEMail];
337 }
338
339 - (iCalPerson *) inReplyAttendee
340 {
341   NSArray *attendees;
342  
343   attendees = [[self inEvent] attendees];
344   if ([attendees count] == 0)
345     return nil;
346   if ([attendees count] > 1)
347     [self warnWithFormat:@"More than one attendee in REPLY: %@", attendees];
348  
349   return [attendees objectAtIndex:0];
350 }
351
352 - (iCalPerson *) storedReplyAttendee
353 {
354   /*
355     TODO: since an attendee can have multiple email addresses, maybe we
356     should translate the email to an internal uid and then retrieve
357     all emails addresses for matching the participant.
358  
359     Note: -findParticipantWithEmail: does not parse the email!
360   */
361   iCalEvent *e;
362   iCalPerson *p;
363
364   p = nil;
365  
366   e = [self storedEvent];
367   if (e)
368     {
369       p = [e findParticipantWithEmail: [self replySenderBaseEMail]];
370       if (!p)
371         p = [e findParticipantWithEmail:[self replySenderEMail]];
372     }
373
374   return p;
375 }
376
377 - (BOOL) isReplySenderAnAttendee
378 {
379   return ([self storedReplyAttendee] != nil);
380 }
381
382 - (iCalPerson *) _emailParticipantWithEvent: (iCalEvent *) event
383 {
384   NSString *emailFrom;
385   SOGoMailObject *mailObject;
386   NGImap4EnvelopeAddress *address;
387
388   mailObject = [[self clientObject] mailObject];
389   address = [[mailObject fromEnvelopeAddresses] objectAtIndex: 0];
390   emailFrom = [address baseEMail];
391
392   return [event findParticipantWithEmail: emailFrom];
393 }
394
395 - (BOOL) hasSenderStatusChanged
396 {
397   iCalPerson *emailParticipant, *calendarParticipant;
398
399   [self inEvent];
400   [self storedEvent];
401   emailParticipant = [self _emailParticipantWithEvent: inEvent];
402   calendarParticipant = [self _emailParticipantWithEvent: storedEvent];
403
404   return ([[emailParticipant partStat]
405             caseInsensitiveCompare: [calendarParticipant partStat]]
406           != NSOrderedSame);
407 }
408
409 @end /* UIxMailPartICalViewer */