From 49cd1cd8ca16c7b7a94445cacc1238a547f3d2ab Mon Sep 17 00:00:00 2001 From: wolfgang Date: Mon, 19 Nov 2007 16:52:21 +0000 Subject: [PATCH] git-svn-id: http://svn.opengroupware.org/SOGo/inverse/trunk@1266 d1b88da0-ebda-0310-925b-ed51d893ca5b --- ChangeLog | 30 ++++++ SoObjects/Mailer/SOGoMailBodyPart.m | 30 +++--- SoObjects/Mailer/SOGoMailObject.h | 52 +++++----- SoObjects/Mailer/SOGoMailObject.m | 18 +++- SoObjects/SOGo/SOGoUser.m | 6 ++ UI/MailPartViewers/UIxMailPartICalActions.m | 20 +++- UI/MailPartViewers/UIxMailPartViewer.m | 13 ++- UI/MailPartViewers/product.plist | 2 +- UI/MailerUI/UIxMailView.m | 5 + UI/Scheduler/UIxComponentEditor.m | 103 ++++++++++++++++---- UI/Scheduler/UIxTaskEditor.m | 28 +++--- UI/Scheduler/product.plist | 15 --- UI/Templates/MailerUI/UIxMailView.wox | 14 +++ 13 files changed, 243 insertions(+), 93 deletions(-) diff --git a/ChangeLog b/ChangeLog index 1f711462..a8167605 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,33 @@ +2007-11-19 Wolfgang Sourdeau + + * UI/Scheduler/UIxComponentEditor.m ([UIxComponentEditor + -toolbar]): rewrote in a way that ensures that each case is + handled properly. + + * SoObjects/SOGo/SOGoUser.m ([SOGoUser -isEqual:otherUser]): new + override method. + + * UI/Scheduler/UIxTaskEditor.m ([-acceptAction]) + ([-declineAction]): commented out unused methods. + + * UI/MailPartViewers/UIxMailPartICalActions.m + ([UIxMailPartICalActions -deleteFromCalendarAction]): actually + delete the found object. + +2007-11-18 Ludovic Marcotte + + * SoObjects/Mailer/SOGoMailBodyPart.m + SoObjects/Mailer/SOGoMailObject.m + UI/MailPartViewers/UIxMailPartViewer.m + Added support of messages containing non-textual + content and no parts. + + * UI/MailerUI/UIxMailView.m + SoObjects/Mailer/SOGoMailObject.m + UI/Templates/MailerUI/UIxMailView.wox + Added support for the Reply-To header upon + message display. + 2007-11-18 Wolfgang Sourdeau * UI/Scheduler/UIxTaskEditor.m ([UIxTaskEditor -saveAction]): diff --git a/SoObjects/Mailer/SOGoMailBodyPart.m b/SoObjects/Mailer/SOGoMailBodyPart.m index 80829127..e770fa92 100644 --- a/SoObjects/Mailer/SOGoMailBodyPart.m +++ b/SoObjects/Mailer/SOGoMailBodyPart.m @@ -179,17 +179,25 @@ static BOOL debugOn = NO; if (data == nil) return nil; /* check for content encodings */ - - if ((enc = [[self partInfo] valueForKey:@"encoding"]) != nil) { - enc = [enc uppercaseString]; - - if ([enc isEqualToString:@"BASE64"]) - data = [data dataByDecodingBase64]; - else if ([enc isEqualToString:@"7BIT"]) - ; /* keep data as is */ // TODO: do we need to change encodings? - else - [self errorWithFormat:@"unsupported encoding: %@", enc]; - } + enc = [[self partInfo] valueForKey: @"encoding"]; + + /* if we haven't found one, check out the main message's encoding + as we could be trying to fetch the message's content as a part */ + if (!enc) + enc = [[[[self mailObject] fetchCoreInfos] valueForKey: @"body"] + valueForKey: @"encoding"]; + + if (enc) + { + enc = [enc uppercaseString]; + + if ([enc isEqualToString:@"BASE64"]) + data = [data dataByDecodingBase64]; + else if ([enc isEqualToString:@"7BIT"]) + ; /* keep data as is */ // TODO: do we need to change encodings? + else + [self errorWithFormat:@"unsupported encoding: %@", enc]; + } return data; } diff --git a/SoObjects/Mailer/SOGoMailObject.h b/SoObjects/Mailer/SOGoMailObject.h index e5d11e82..fa0b5458 100644 --- a/SoObjects/Mailer/SOGoMailObject.h +++ b/SoObjects/Mailer/SOGoMailObject.h @@ -37,8 +37,15 @@ would address the MIME part 1.2.3 of the mail 12345 in the folder INBOX. */ -@class NSData, NSString, NSArray, NSCalendarDate, NSException, NSDictionary; -@class NGImap4Envelope, NGImap4EnvelopeAddress; +@class NSArray; +@class NSCalendarDate; +@class NSData; +@class NSDictionary; +@class NSException; +@class NSString; + +@class NGImap4Envelope; +@class NGImap4EnvelopeAddress; @interface SOGoMailObject : SOGoMailBaseObject { @@ -53,42 +60,43 @@ /* core infos */ -- (BOOL)doesMailExist; -- (id)fetchCoreInfos; // TODO: what does it do? +- (BOOL) doesMailExist; +- (id) fetchCoreInfos; // TODO: what does it do? -- (NGImap4Envelope *)envelope; -- (NSString *)subject; -- (NSString *)decodedSubject; -- (NSCalendarDate *)date; -- (NSArray *)fromEnvelopeAddresses; -- (NSArray *)toEnvelopeAddresses; -- (NSArray *)ccEnvelopeAddresses; +- (NGImap4Envelope *) envelope; +- (NSString *) subject; +- (NSString *) decodedSubject; +- (NSCalendarDate *) date; +- (NSArray *) fromEnvelopeAddresses; +- (NSArray *) replyToEnvelopeAddresses; +- (NSArray *) toEnvelopeAddresses; +- (NSArray *) ccEnvelopeAddresses; - (NSDictionary *) mailHeaders; -- (id)bodyStructure; -- (id)lookupInfoForBodyPart:(id)_path; +- (id) bodyStructure; +- (id) lookupInfoForBodyPart:(id)_path; /* content */ -- (NSData *)content; -- (NSString *)contentAsString; +- (NSData *) content; +- (NSString *) contentAsString; /* bulk fetching of plain/text content */ -- (NSArray *)plainTextContentFetchKeys; -- (NSDictionary *)fetchPlainTextParts:(NSArray *)_fetchKeys; -- (NSDictionary *)fetchPlainTextParts; -- (NSDictionary *)fetchPlainTextStrings:(NSArray *)_fetchKeys; +- (NSArray *) plainTextContentFetchKeys; +- (NSDictionary *) fetchPlainTextParts:(NSArray *)_fetchKeys; +- (NSDictionary *) fetchPlainTextParts; +- (NSDictionary *) fetchPlainTextStrings:(NSArray *)_fetchKeys; /* flags */ -- (NSException *)addFlags:(id)_f; -- (NSException *)removeFlags:(id)_f; +- (NSException *) addFlags:(id)_f; +- (NSException *) removeFlags:(id)_f; /* deletion */ -- (BOOL)isDeletionAllowed; +- (BOOL) isDeletionAllowed; - (NSException *) trashInContext:(id)_ctx; - (NSException *) copyToFolderNamed: (NSString *) folderName inContext: (id)_ctx; diff --git a/SoObjects/Mailer/SOGoMailObject.m b/SoObjects/Mailer/SOGoMailObject.m index 4c44bd99..c2a5bd0e 100644 --- a/SoObjects/Mailer/SOGoMailObject.m +++ b/SoObjects/Mailer/SOGoMailObject.m @@ -296,6 +296,11 @@ static BOOL debugSoParts = NO; return [[self envelope] cc]; } +- (NSArray *) replyToEnvelopeAddresses +{ + return [[self envelope] replyTo]; +} + - (NSData *) mailHeaderData { return [[self fetchCoreInfos] valueForKey: @"header"]; @@ -460,6 +465,7 @@ static BOOL debugSoParts = NO; { if ([content isKindOfClass: [NSData class]]) { +#warning we ignore the charset here? s = [[NSString alloc] initWithData: content encoding: NSISOLatin1StringEncoding]; if (s) @@ -747,6 +753,14 @@ static BOOL debugSoParts = NO; NSString *mimeType; parts = [[self bodyStructure] objectForKey: @"parts"]; + + /* We don't have parts here but we're trying to download the message's + content that could be an image/jpeg, as an example */ + if ([parts count] == 0) + { + return [SOGoMailBodyPart objectWithName: @"1" inContainer: self]; + } + part = [_key intValue] - 1; if (part > -1 && part < [parts count]) { @@ -924,13 +938,13 @@ static BOOL debugSoParts = NO; - (NSException *) copyToFolderNamed: (NSString *) folderName inContext: (id)_ctx { - SOGoMailAccounts *destFolder; + SOGoMailFolder *destFolder; NSEnumerator *folders; NSString *currentFolderName, *reason; // TODO: check for safe HTTP method - destFolder = [self mailAccountsFolder]; + destFolder = (SOGoMailFolder *) [self mailAccountsFolder]; folders = [[folderName componentsSeparatedByString: @"/"] objectEnumerator]; currentFolderName = [folders nextObject]; currentFolderName = [folders nextObject]; diff --git a/SoObjects/SOGo/SOGoUser.m b/SoObjects/SOGo/SOGoUser.m index 95f32ac9..e81214d5 100644 --- a/SoObjects/SOGo/SOGoUser.m +++ b/SoObjects/SOGo/SOGoUser.m @@ -606,4 +606,10 @@ NSString *SOGoWeekStartFirstFullWeek = @"FirstFullWeek"; return rolesForObject; } +- (BOOL) isEqual: (id) otherUser +{ + return ([otherUser isKindOfClass: [SoUser class]] + && [login isEqualToString: [otherUser login]]); +} + @end /* SOGoUser */ diff --git a/UI/MailPartViewers/UIxMailPartICalActions.m b/UI/MailPartViewers/UIxMailPartICalActions.m index e51f518c..e695de0d 100644 --- a/UI/MailPartViewers/UIxMailPartICalActions.m +++ b/UI/MailPartViewers/UIxMailPartICalActions.m @@ -67,11 +67,21 @@ { SOGoAppointmentFolder *personalFolder; SOGoAppointmentObject *eventObject; + NSString *cname; + + eventObject = nil; personalFolder = [user personalCalendarFolderInContext: context]; - eventObject = [personalFolder lookupName: uid - inContext: context acquire: NO]; - if (![eventObject isKindOfClass: [SOGoAppointmentObject class]]) + cname = [personalFolder resourceNameForEventUID: uid]; + if (cname) + { + eventObject = [personalFolder lookupName: cname + inContext: context acquire: NO]; + if (![eventObject isKindOfClass: [SOGoAppointmentObject class]]) + eventObject = nil; + } + + if (!eventObject) eventObject = [SOGoAppointmentObject objectWithName: uid inContainer: personalFolder]; @@ -96,7 +106,8 @@ chosenEvent = emailEvent; else { - calendarEvent = (iCalEvent *) [*eventObject component: NO secure: NO]; + calendarEvent = (iCalEvent *) [*eventObject component: NO + secure: NO]; if ([calendarEvent compare: emailEvent] == NSOrderedAscending) chosenEvent = emailEvent; else @@ -199,6 +210,7 @@ if (emailEvent) { eventObject = [self _eventObjectWithUID: [emailEvent uid]]; + [eventObject delete]; response = [self responseWith204]; } else diff --git a/UI/MailPartViewers/UIxMailPartViewer.m b/UI/MailPartViewers/UIxMailPartViewer.m index 78a8fc8e..3639789c 100644 --- a/UI/MailPartViewers/UIxMailPartViewer.m +++ b/UI/MailPartViewers/UIxMailPartViewer.m @@ -312,9 +312,16 @@ if (![url hasSuffix: @"/"]) url = [url stringByAppendingString: @"/"]; - /* mail relative path to body-part */ - - /* eg this was nil for a draft containing an HTML message */ + /* if we get a message with an image/* or application/* + Content-Type, we must generate a 'fake' part since our + decoded mail won't have any. Also see SOGoMailBodyPart: -fetchBLOB + and SOGoMailObject: -lookupImap4BodyPartKey: inContext for + other workarounds */ + if (!partPath || [partPath count] == 0) + partPath = [NSArray arrayWithObject: @"0"]; + + /* mail relative path to body-part + eg this was nil for a draft containing an HTML message */ if ([(n = [partPath componentsJoinedByString:@"/"]) isNotNull]) url = [url stringByAppendingString:n]; diff --git a/UI/MailPartViewers/product.plist b/UI/MailPartViewers/product.plist index ddf40447..cdf98f67 100644 --- a/UI/MailPartViewers/product.plist +++ b/UI/MailPartViewers/product.plist @@ -37,7 +37,7 @@ }; */ deleteFromCalendar = { protectedBy = "View"; - actionClass = "UIxMailPartICalAction"; + actionClass = "UIxMailPartICalActions"; actionName = "deleteFromCalendar"; }; }; diff --git a/UI/MailerUI/UIxMailView.m b/UI/MailerUI/UIxMailView.m index 986b2674..56c88a9d 100644 --- a/UI/MailerUI/UIxMailView.m +++ b/UI/MailerUI/UIxMailView.m @@ -131,6 +131,11 @@ static NSString *mailETag = nil; return [[[self clientObject] ccEnvelopeAddresses] count] > 0 ? YES : NO; } +- (BOOL) hasReplyTo +{ + return [[[self clientObject] replyToEnvelopeAddresses] count] > 0 ? YES : NO; +} + /* viewers */ - (id) contentViewerComponent diff --git a/UI/Scheduler/UIxComponentEditor.m b/UI/Scheduler/UIxComponentEditor.m index 04e4ee1a..3916100f 100644 --- a/UI/Scheduler/UIxComponentEditor.m +++ b/UI/Scheduler/UIxComponentEditor.m @@ -41,11 +41,13 @@ #import #import +#import #import #import #import #import #import +#import #import #import #import @@ -904,27 +906,18 @@ [component setLastModified: now]; } -- (NSString *) toolbar +#warning the following methods probably share some code... +- (NSString *) _toolbarForOwner: (SOGoUser *) ownerUser { - SOGoCalendarComponent *clientObject; NSString *toolbarFilename; - iCalPerson *participant; iCalPersonPartStat participationStatus; - SoSecurityManager *sm; - NSString *owner; - - sm = [SoSecurityManager sharedSecurityManager]; - clientObject = [self clientObject]; - owner = [clientObject ownerInContext: context]; - participant = [clientObject findParticipantWithUID: owner]; - - if (participant - && ![sm validatePermission: SOGoCalendarPerm_RespondToComponent - onObject: clientObject - inContext: context]) + if ([[component attendees] count] + && [component userIsParticipant: ownerUser] + && ![component userIsOrganizer: ownerUser]) { - participationStatus = [participant participationStatus]; + participationStatus + = [[component findParticipant: ownerUser] participationStatus]; /* Lightning does not manage participation status within tasks */ if (participationStatus == iCalPersonPartStatAccepted) toolbarFilename = @"SOGoAppointmentObjectDecline.toolbar"; @@ -933,17 +926,85 @@ else toolbarFilename = @"SOGoAppointmentObjectAcceptOrDecline.toolbar"; } - else if (![sm validatePermission: SOGoCalendarPerm_ModifyComponent - onObject: clientObject - inContext: context]) + else { - if ([[clientObject componentTag] isEqualToString: @"vevent"]) + if ([component isKindOfClass: [iCalEvent class]]) toolbarFilename = @"SOGoAppointmentObject.toolbar"; else toolbarFilename = @"SOGoTaskObject.toolbar"; } + + return toolbarFilename; +} + +- (NSString *) _toolbarForDelegate: (SOGoUser *) ownerUser +{ + SOGoCalendarComponent *clientObject; + SoSecurityManager *sm; + NSString *toolbarFilename, *adminToolbar; + iCalPersonPartStat participationStatus; + + clientObject = [self clientObject]; + + if ([component isKindOfClass: [iCalEvent class]]) + adminToolbar = @"SOGoAppointmentObject.toolbar"; else - toolbarFilename = @"SOGoComponentClose.toolbar"; + adminToolbar = @"SOGoTaskObject.toolbar"; + + sm = [SoSecurityManager sharedSecurityManager]; + if ([[component attendees] count]) + { + if ([component userIsOrganizer: ownerUser] + && ![sm validatePermission: SOGoCalendarPerm_ModifyComponent + onObject: clientObject + inContext: context]) + toolbarFilename = adminToolbar; + else if ([component userIsParticipant: ownerUser] + && ![sm validatePermission: SOGoCalendarPerm_RespondToComponent + onObject: clientObject + inContext: context]) + { + participationStatus + = [[component findParticipant: ownerUser] participationStatus]; + /* Lightning does not manage participation status within tasks */ + if (participationStatus == iCalPersonPartStatAccepted) + toolbarFilename = @"SOGoAppointmentObjectDecline.toolbar"; + else if (participationStatus == iCalPersonPartStatDeclined) + toolbarFilename = @"SOGoAppointmentObjectAccept.toolbar"; + else + toolbarFilename = @"SOGoAppointmentObjectAcceptOrDecline.toolbar"; + } + else + toolbarFilename = @"SOGoComponentClose.toolbar"; + } + else + { + if (![sm validatePermission: SOGoCalendarPerm_ModifyComponent + onObject: clientObject + inContext: context]) + toolbarFilename = adminToolbar; + else + toolbarFilename = @"SOGoComponentClose.toolbar"; + } + + return toolbarFilename; +} + +- (NSString *) toolbar +{ + SOGoCalendarComponent *clientObject; + NSString *toolbarFilename; + SOGoUser *ownerUser; + + clientObject = [self clientObject]; + ownerUser = [SOGoUser userWithLogin: [clientObject ownerInContext: context] + roles: nil]; + + if ([ownerUser isEqual: [context activeUser]]) + toolbarFilename = [self _toolbarForOwner: ownerUser]; + else + toolbarFilename = [self _toolbarForDelegate: ownerUser]; + return toolbarFilename; } diff --git a/UI/Scheduler/UIxTaskEditor.m b/UI/Scheduler/UIxTaskEditor.m index 41c39fc9..96d52081 100644 --- a/UI/Scheduler/UIxTaskEditor.m +++ b/UI/Scheduler/UIxTaskEditor.m @@ -411,23 +411,23 @@ // TODO: add tentatively -- (id) acceptOrDeclineAction: (BOOL) _accept -{ - [[self clientObject] changeParticipationStatus: - _accept ? @"ACCEPTED" : @"DECLINED"]; +// - (id) acceptOrDeclineAction: (BOOL) _accept +// { +// [[self clientObject] changeParticipationStatus: +// _accept ? @"ACCEPTED" : @"DECLINED"]; - return self; -} +// return self; +// } -- (id) acceptAction -{ - return [self acceptOrDeclineAction: YES]; -} +// - (id) acceptAction +// { +// return [self acceptOrDeclineAction: YES]; +// } -- (id) declineAction -{ - return [self acceptOrDeclineAction: NO]; -} +// - (id) declineAction +// { +// return [self acceptOrDeclineAction: NO]; +// } - (id) changeStatusAction { diff --git a/UI/Scheduler/product.plist b/UI/Scheduler/product.plist index 6ee2a5af..734735ff 100644 --- a/UI/Scheduler/product.plist +++ b/UI/Scheduler/product.plist @@ -179,11 +179,6 @@ }; }; methods = { -// delete = { -// protectedBy = "Delete Objects"; -// pageName = "UIxTaskView"; -// actionName = "delete"; -// }; edit = { protectedBy = "ViewAllComponent"; pageName = "UIxTaskEditor"; @@ -207,16 +202,6 @@ pageName = "UIxTaskEditor"; actionName = "changeStatus"; }; - accept = { - protectedBy = "RespondToComponent"; - pageName = "UIxTaskEditor"; - actionName = "accept"; - }; - decline = { - protectedBy = "RespondToComponent"; - pageName = "UIxTaskEditor"; - actionName = "decline"; - }; }; }; }; diff --git a/UI/Templates/MailerUI/UIxMailView.wox b/UI/Templates/MailerUI/UIxMailView.wox index de0d6526..a91268ae 100644 --- a/UI/Templates/MailerUI/UIxMailView.wox +++ b/UI/Templates/MailerUI/UIxMailView.wox @@ -66,6 +66,20 @@ + + + : + + + + + + +
-- 2.39.5