2 Copyright (C) 2004-2005 SKYRIX Software AG
4 This file is part of OpenGroupware.org.
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
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.
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
25 Show plain/calendar mail parts.
28 #import <NGObjWeb/WOResponse.h>
30 #import <NGExtensions/NSCalendarDate+misc.h>
31 #import <NGExtensions/NSObject+Logs.h>
33 #import <NGImap4/NGImap4EnvelopeAddress.h>
35 #import <NGCards/iCalCalendar.h>
36 #import <NGCards/iCalEvent.h>
37 #import <NGCards/iCalPerson.h>
38 #import <NGCards/iCalDateTime.h>
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>
48 #import "UIxMailPartICalViewer.h"
50 @implementation UIxMailPartICalViewer
54 [storedEventObject release];
55 [storedEvent release];
60 [dateFormatter release];
66 - (void) resetPathCaches
68 [super resetPathCaches];
69 [inEvent release]; inEvent = nil;
70 [inCalendar release]; inCalendar = nil;
71 [storedEventObject release]; storedEventObject = nil;
72 [storedEvent release]; storedEvent = nil;
74 /* not strictly path-related, but useless without it anyway: */
75 [attendee release]; attendee = nil;
76 [item release]; item = nil;
79 /* raw content handling */
81 - (NSStringEncoding) fallbackStringEncoding
84 iCalendar invitations sent by Outlook 2002 have the annoying bug that the
85 mail states an UTF-8 content encoding but the actual iCalendar content is
86 encoding in Latin-1 (or Windows Western?).
88 As a result the content decoding will fail (TODO: always?). In this case we
89 try to decode with Latin-1.
91 Note: we could check for the Outlook x-mailer, but it was considered better
92 to try Latin-1 as a fallback in any case (be tolerant).
94 return NSISOLatin1StringEncoding;
99 - (iCalCalendar *) inCalendar
104 = [iCalCalendar parseSingleFromSource: [self flatContentAsString]];
111 - (BOOL) couldParseCalendar
113 return (([self inCalendar]));
116 - (iCalEvent *) inEvent
122 events = [[self inCalendar] events];
123 if ([events count] > 0)
124 inEvent = [[events objectAtIndex:0] retain];
132 - (SOGoDateFormatter *) dateFormatter
136 dateFormatter = [[context activeUser] dateFormatterInContext: context];
137 [dateFormatter retain];
140 return dateFormatter;
143 /* below is copied from UIxAppointmentView, can we avoid that? */
145 - (void) setAttendee: (id) _attendee
147 ASSIGN (attendee, _attendee);
155 - (NSString *) _personForDisplay: (iCalPerson *) person
157 NSString *fn, *email, *result;
159 fn = [person cnWithoutQuotes];
160 email = [person rfc822Email];
162 result = [NSString stringWithFormat: @"%@ <%@>",
170 - (NSString *) attendeeForDisplay
172 return [self _personForDisplay: attendee];
175 - (void) setItem: (id) _item
185 - (NSCalendarDate *) startTime
187 NSCalendarDate *date;
188 NSTimeZone *timeZone;
190 date = [[self authorativeEvent] startDate];
191 timeZone = [[context activeUser] timeZone];
192 [date setTimeZone: timeZone];
197 - (NSCalendarDate *) endTime
199 NSCalendarDate *date;
200 NSTimeZone *timeZone;
202 date = [[self authorativeEvent] endDate];
203 timeZone = [[context activeUser] timeZone];
204 [date setTimeZone: timeZone];
209 - (BOOL) isEndDateOnSameDay
211 return [[self startTime] isDateOnSameDay:[self endTime]];
214 - (NSTimeInterval) duration
216 return [[self endTime] timeIntervalSinceDate:[self startTime]];
219 /* calendar folder support */
221 - (SOGoAppointmentFolder *) calendarFolder
223 /* return scheduling calendar of currently logged-in user */
227 user = [context activeUser];
228 folder = [[user homeFolderInContext: context] lookupName: @"Calendar"
232 return [folder lookupName: @"personal" inContext: context acquire: NO];
235 - (SOGoAppointmentObject *) storedEventObject
237 /* lookup object in the users Calendar */
238 SOGoAppointmentFolder *calendar;
241 if (!storedEventObject)
243 calendar = [self calendarFolder];
244 if ([calendar isKindOfClass: [NSException class]])
245 [self errorWithFormat:@"Did not find Calendar folder: %@", calendar];
248 filename = [calendar resourceNameForEventUID:[[self inEvent] uid]];
251 storedEventObject = [calendar lookupName: filename
252 inContext: [self context]
254 if ([storedEventObject isKindOfClass: [NSException class]])
255 storedEventObject = nil;
257 [storedEventObject retain];
262 return storedEventObject;
265 - (BOOL) isEventStoredInCalendar
267 return (([self storedEventObject]));
270 - (iCalEvent *) storedEvent
274 storedEvent = [[self storedEventObject] component: NO secure: NO];
275 [storedEvent retain];
281 /* organizer tracking */
283 - (NSString *) loggedInUserEMail
285 NSDictionary *identity;
287 identity = [[context activeUser] primaryIdentity];
289 return [identity objectForKey: @"email"];
292 - (iCalEvent *) authorativeEvent
294 iCalEvent *authorativeEvent;
298 || ([storedEvent compare: [self inEvent]] == NSOrderedAscending))
299 authorativeEvent = inEvent;
301 authorativeEvent = [self storedEvent];
303 return authorativeEvent;
306 - (BOOL) isLoggedInUserTheOrganizer
308 return [[self authorativeEvent] userIsOrganizer: [context activeUser]];
311 - (BOOL) isLoggedInUserAnAttendee
313 return [[self authorativeEvent] userIsParticipant: [context activeUser]];
318 - (NSString *) organizerDisplayName
320 iCalPerson *organizer;
323 organizer = [[self authorativeEvent] organizer];
325 value = [self _personForDisplay: organizer];
327 value = @"[todo: no organizer set, use 'from']";
334 - (NGImap4EnvelopeAddress *) replySenderAddress
337 The iMIP reply is the sender of the mail, the 'attendees' are NOT set to
338 the actual attendees. BUT the attendee field contains the reply-status!
342 tmp = [[self clientObject] fromEnvelopeAddresses];
343 if ([tmp count] == 0) return nil;
344 return [tmp objectAtIndex:0];
347 - (NSString *) replySenderEMail
349 return [[self replySenderAddress] email];
352 - (NSString *) replySenderBaseEMail
354 return [[self replySenderAddress] baseEMail];
357 - (iCalPerson *) inReplyAttendee
361 attendees = [[self inEvent] attendees];
362 if ([attendees count] == 0)
364 if ([attendees count] > 1)
365 [self warnWithFormat:@"More than one attendee in REPLY: %@", attendees];
367 return [attendees objectAtIndex:0];
370 - (iCalPerson *) storedReplyAttendee
373 TODO: since an attendee can have multiple email addresses, maybe we
374 should translate the email to an internal uid and then retrieve
375 all emails addresses for matching the participant.
377 Note: -findParticipantWithEmail: does not parse the email!
384 e = [self storedEvent];
387 p = [e findParticipantWithEmail: [self replySenderBaseEMail]];
389 p = [e findParticipantWithEmail:[self replySenderEMail]];
395 - (BOOL) isReplySenderAnAttendee
397 return (([self storedReplyAttendee]));
400 - (iCalPerson *) _emailParticipantWithEvent: (iCalEvent *) event
403 SOGoMailObject *mailObject;
404 NGImap4EnvelopeAddress *address;
406 mailObject = [[self clientObject] mailObject];
407 address = [[mailObject fromEnvelopeAddresses] objectAtIndex: 0];
408 emailFrom = [address baseEMail];
410 return [event findParticipantWithEmail: emailFrom];
413 - (BOOL) hasSenderStatusChanged
415 iCalPerson *emailParticipant, *calendarParticipant;
419 emailParticipant = [self _emailParticipantWithEvent: inEvent];
420 calendarParticipant = [self _emailParticipantWithEvent: storedEvent];
422 return ([[emailParticipant partStat]
423 caseInsensitiveCompare: [calendarParticipant partStat]]
427 @end /* UIxMailPartICalViewer */