diff --git a/ChangeLog b/ChangeLog index 6cf4ed546..53a2270d6 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,60 @@ +2007-09-11 Wolfgang Sourdeau + + * SoObjects/SOGo/SOGoFolder.m ([SOGoFolder + +folderWithName:aNameandDisplayName:aDisplayNameinContainer:aContainer]): + new method. + ([SOGoFolder -displayName]): new method. + ([SOGoFolder -delete]): accept to proceed only if nameInContainer + != "personal". + + * SoObjects/Contacts/SOGoContactLDAPFolder.m + ([SOGoContactLDAPFolder + +folderWithName:aNameandDisplayName:aDisplayNameinContainer:aContainer]): + renamed from "contactFolderWithName..." for compatibility with SOGoFolder. + + * SoObjects/Contacts/SOGoContactGCSFolder.m ([SOGoContactGCSFolder + +contactFolderWithName:aNameandDisplayName:aDisplayNameinContainer:aContainer]): + removed method, reimplemented in SOGoFolder. + ([SOGoContactGCSFolder -displayName]): removed method, + reimplemented in SOGoFolder. + ([-delete]): removed method, modified in SOGoFolder. + + * SoObjects/Contacts/SOGoContactFolders.[hm]: modified class to be + a subclass of SOGoParentFolder. + + * SoObjects/SOGo/SOGoParentFolder.[hm]: new class module derived + from SOGoContactFolders and modified to be more content-independent. + + * UI/MailerUI/UIxMailActions.m ([UIxMailActions -markMessageUnreadAction]) + ([UIxMailActions -markMessageReadAction]): new methods moved from + UIxMailListView and adapted to invoke the client object directly, + since the previous versions had to to a lookup from the parent + SOGoMailFolder. + + * UI/MailerUI/UIxMailListView.m ([-markMessageUnreadAction]): move + method into UIxMailActions. + ([-markMessageReadAction]): same as above. + ([-viewAction]): removed useless method. + ([-javaScriptOK]): removed useless method. + ([-isJavaScriptRequest]): removed useless method. + ([-lookupActiveMessage]): removed useless method. + + * UI/Common/WODirectAction+SOGo.m ([WODirectAction + -responseWithStatus:status]): new method that returns a WOResponse + initialized with the specified status code. + ([WODirectAction -responseWith204]): new method that invokes the + above one with "204" as parameter. + ([WODirectAction -redirectToLocation:newLocation]): rewrote method + to make use of -responseWithStatus:. + + * UI/SOGoUI/UIxComponent.m ([UIxComponent -responseWith204]): new + method that returns a WOResponse initialized with the 204 status + code. + + * UI/MailerUI/UIxMailListView.m ([UIxMailListView -sortedUIDs]): + always use a "not deleted" search qualifier along with the user + qualifier (if present). + 2007-09-10 Wolfgang Sourdeau * UI/Contacts/UIxContactFoldersView.m ([UIxContactFoldersView diff --git a/SoObjects/Contacts/SOGoContactFolder.h b/SoObjects/Contacts/SOGoContactFolder.h index 6ced261a5..c1ff89685 100644 --- a/SoObjects/Contacts/SOGoContactFolder.h +++ b/SoObjects/Contacts/SOGoContactFolder.h @@ -43,16 +43,6 @@ @protocol SOGoContactFolder -+ (id ) contactFolderWithName: (NSString *) aName - andDisplayName: (NSString *) aDisplayName - inContainer: (SOGoObject *) aContainer; - -- (id ) initWithName: (NSString *) aName - andDisplayName: (NSString *) aDisplayName - inContainer: (SOGoObject *) aContainer; - -- (NSString *) displayName; - - (NSArray *) lookupContactsWithFilter: (NSString *) filter sortBy: (NSString *) sortKey ordering: (NSComparisonResult) sortOrdering; diff --git a/SoObjects/Contacts/SOGoContactFolders.h b/SoObjects/Contacts/SOGoContactFolders.h index 0272f3bbb..4e271e5cf 100644 --- a/SoObjects/Contacts/SOGoContactFolders.h +++ b/SoObjects/Contacts/SOGoContactFolders.h @@ -1,6 +1,6 @@ /* SOGoContactFolders.h - this file is part of SOGo * - * Copyright (C) 2006 Inverse groupe conseil + * Copyright (C) 2006, 2007 Inverse groupe conseil * * Author: Wolfgang Sourdeau * @@ -23,25 +23,9 @@ #ifndef SOGOCONTACTFOLDERS_H #define SOGOCONTACTFOLDERS_H -#import +#import -@class NSMutableDictionary; -@class NSString; -@class WOResponse; - -@interface SOGoContactFolders : SOGoObject -{ - NSMutableDictionary *contactFolders; - NSString *OCSPath; -} - -- (NSString *) defaultSourceName; - -- (void) setBaseOCSPath: (NSString *) newOCSPath; - -- (NSArray *) contactFolders; - -- (WOResponse *) newFolderWithName: (NSString *) name; +@interface SOGoContactFolders : SOGoParentFolder @end diff --git a/SoObjects/Contacts/SOGoContactFolders.m b/SoObjects/Contacts/SOGoContactFolders.m index 215870978..dc3ffe256 100644 --- a/SoObjects/Contacts/SOGoContactFolders.m +++ b/SoObjects/Contacts/SOGoContactFolders.m @@ -1,6 +1,6 @@ /* SOGoContactFolders.m - this file is part of SOGo * - * Copyright (C) 2006 Inverse groupe conseil + * Copyright (C) 2006, 2007 Inverse groupe conseil * * Author: Wolfgang Sourdeau * @@ -20,7 +20,6 @@ * Boston, MA 02111-1307, USA. */ -/* exchange folder types: */ /* MailItems IPF.Note ContactItems IPF.Contact AppointmentItems IPF.Appointment @@ -28,23 +27,25 @@ TaskItems IPF.Task JournalItems IPF.Journal */ -#import +// #import +#import #import +#import -#import -#import -#import -#import -#import -#import +// #import +// #import +// #import +// #import +// #import +// #import -#import -#import -#import -#import +// #import +// #import +// #import +// #import #import -#import +// #import #import "SOGoContactGCSFolder.h" #import "SOGoContactLDAPFolder.h" @@ -52,89 +53,14 @@ @implementation SOGoContactFolders -- (id) init ++ (NSString *) gcsFolderType { - if ((self = [super init])) - { - contactFolders = nil; - OCSPath = nil; - } - - return self; + return @"Contact"; } -- (void) dealloc ++ (Class) subFolderClass { - if (contactFolders) - [contactFolders release]; - if (OCSPath) - [OCSPath release]; - [super dealloc]; -} - -- (void) _fetchPersonalFolders: (NSString *) sql - withChannel: (EOAdaptorChannel *) fc -{ - NSArray *attrs; - NSDictionary *row; - SOGoContactGCSFolder *ab; - BOOL hasPersonal; - NSString *key, *path; - - hasPersonal = NO; - [fc evaluateExpressionX: sql]; - attrs = [fc describeResults: NO]; - row = [fc fetchAttributes: attrs withZone: NULL]; - while (row) - { - ab = [SOGoContactGCSFolder - contactFolderWithName: [row objectForKey: @"c_path4"] - andDisplayName: [row objectForKey: @"c_foldername"] - inContainer: self]; - key = [row objectForKey: @"c_path4"]; - hasPersonal = (hasPersonal || [key isEqualToString: @"personal"]); - [ab setOCSPath: [NSString stringWithFormat: @"%@/%@", - OCSPath, key]]; - [contactFolders setObject: ab forKey: key]; - row = [fc fetchAttributes: attrs withZone: NULL]; - } - - if (!hasPersonal) - { - ab = [SOGoContactGCSFolder contactFolderWithName: @"personal" - andDisplayName: @"Contacts" - inContainer: self]; - path = [NSString stringWithFormat: - @"/Users/%@/Contacts/personal", - [self ownerInContext: context]]; - [ab setOCSPath: path]; - [contactFolders setObject: ab forKey: @"personal"]; - } -} - -- (void) appendPersonalSources -{ - GCSChannelManager *cm; - EOAdaptorChannel *fc; - NSURL *folderLocation; - NSString *sql; - - cm = [GCSChannelManager defaultChannelManager]; - folderLocation - = [[GCSFolderManager defaultFolderManager] folderInfoLocation]; - fc = [cm acquireOpenChannelForURL: folderLocation]; - if (fc) - { - sql = [NSString - stringWithFormat: (@"SELECT c_path4, c_foldername FROM %@" - @" WHERE c_path2 = '%@'" - @" AND c_folder_type = 'Contact'"), - [folderLocation gcsTableName], [self ownerInContext: context]]; - [self _fetchPersonalFolders: sql withChannel: fc]; - [cm releaseChannel: fc]; -// sql = [sql stringByAppendingFormat:@" WHERE %@ = '%@'", -// uidColumnName, [self uid]]; - } + return [SOGoContactGCSFolder class]; } - (void) appendSystemSources @@ -150,119 +76,13 @@ while (currentSourceID) { displayName = [um displayNameForSourceWithID: currentSourceID]; - currentFolder = [SOGoContactLDAPFolder contactFolderWithName: currentSourceID + currentFolder = [SOGoContactLDAPFolder folderWithName: currentSourceID andDisplayName: displayName inContainer: self]; [currentFolder setLDAPSource: [um sourceWithID: currentSourceID]]; - [contactFolders setObject: currentFolder forKey: currentSourceID]; + [subFolders setObject: currentFolder forKey: currentSourceID]; currentSourceID = [sourceIDs nextObject]; } } -- (WOResponse *) newFolderWithName: (NSString *) name -{ - SOGoContactGCSFolder *newFolder; - WOResponse *response; - - newFolder = [SOGoContactGCSFolder contactFolderWithName: name - andDisplayName: name - inContainer: self]; - if ([newFolder isKindOfClass: [NSException class]]) - response = (WOResponse *) newFolder; - else - { - [newFolder setOCSPath: [NSString stringWithFormat: @"%@/%@", - OCSPath, name]]; - if ([newFolder create]) - { - response = [WOResponse new]; - [response setStatus: 201]; - [response autorelease]; - } - else - response = [NSException exceptionWithHTTPStatus: 400 - reason: @"The new folder could not be created"]; - } - - return response; -} - -- (void) initContactSources -{ - if (!contactFolders) - { - contactFolders = [NSMutableDictionary new]; - [self appendPersonalSources]; - [self appendSystemSources]; - } -} - -- (id) lookupName: (NSString *) name - inContext: (WOContext *) lookupContext - acquire: (BOOL) acquire -{ - id obj; - - /* first check attributes directly bound to the application */ - obj = [super lookupName: name inContext: lookupContext acquire: NO]; - if (!obj) - { - if (!contactFolders) - [self initContactSources]; - - obj = [contactFolders objectForKey: name]; - if (!obj) - obj = [NSException exceptionWithHTTPStatus: 404]; - } - - return obj; -} - -- (NSArray *) toManyRelationshipKeys -{ - if (!contactFolders) - [self initContactSources]; - - return [contactFolders allKeys]; -} - -- (NSArray *) contactFolders -{ - if (!contactFolders) - [self initContactSources]; - - return [contactFolders allValues]; -} - -/* acls */ -- (NSArray *) aclsForUser: (NSString *) uid -{ - return nil; -} - -- (BOOL) davIsCollection -{ - return YES; -} - -- (NSString *) davContentType -{ - return @"httpd/unix-directory"; -} - -- (void) setBaseOCSPath: (NSString *) newOCSPath -{ - if (OCSPath) - [OCSPath release]; - OCSPath = newOCSPath; - if (OCSPath) - [OCSPath retain]; -} - -/* web interface */ -- (NSString *) defaultSourceName -{ - return @"personal"; -} - @end diff --git a/SoObjects/Contacts/SOGoContactGCSFolder.h b/SoObjects/Contacts/SOGoContactGCSFolder.h index 1dd91a53b..d10913d0b 100644 --- a/SoObjects/Contacts/SOGoContactGCSFolder.h +++ b/SoObjects/Contacts/SOGoContactGCSFolder.h @@ -30,9 +30,6 @@ @class NSString; @interface SOGoContactGCSFolder : SOGoFolder -{ - NSString *displayName; -} @end diff --git a/SoObjects/Contacts/SOGoContactGCSFolder.m b/SoObjects/Contacts/SOGoContactGCSFolder.m index 47eb5f13c..a3f603185 100644 --- a/SoObjects/Contacts/SOGoContactGCSFolder.m +++ b/SoObjects/Contacts/SOGoContactGCSFolder.m @@ -41,47 +41,11 @@ @implementation SOGoContactGCSFolder -+ (id ) contactFolderWithName: (NSString *) aName - andDisplayName: (NSString *) aDisplayName - inContainer: (SOGoObject *) aContainer -{ - SOGoContactGCSFolder *folder; - - folder = [[self alloc] initWithName: aName - andDisplayName: aDisplayName - inContainer: aContainer]; - [folder autorelease]; - - return folder; -} - -- (void) dealloc -{ - [displayName release]; - [super dealloc]; -} - -- (id ) initWithName: (NSString *) newName - andDisplayName: (NSString *) newDisplayName - inContainer: (SOGoObject *) newContainer -{ - if ((self = [self initWithName: newName - inContainer: newContainer])) - ASSIGN (displayName, newDisplayName); - - return self; -} - - (BOOL) folderIsMandatory { return [nameInContainer isEqualToString: @"personal"]; } -- (NSString *) displayName -{ - return displayName; -} - /* name lookup */ - (id ) lookupContactWithId: (NSString *) recordId @@ -105,7 +69,6 @@ BOOL isPut; isPut = NO; - /* first check attributes directly bound to the application */ obj = [super lookupName:_key inContext:_ctx acquire:NO]; if (!obj) { @@ -273,14 +236,6 @@ return @"vcard-collection"; } -- (NSException *) delete -{ - return (([nameInContainer isEqualToString: @"personal"]) - ? [NSException exceptionWithHTTPStatus: 403 - reason: @"the 'personal' folder cannot be deleted"] - : [super delete]); -} - // /* GET */ // - (id) GETAction: (id)_ctx diff --git a/SoObjects/Contacts/SOGoContactLDAPFolder.h b/SoObjects/Contacts/SOGoContactLDAPFolder.h index ad1ceb89c..e405a3faf 100644 --- a/SoObjects/Contacts/SOGoContactLDAPFolder.h +++ b/SoObjects/Contacts/SOGoContactLDAPFolder.h @@ -37,9 +37,12 @@ BOOL ignoreSoObjectHunger; } -- (id ) initWithName: (NSString *) newName - andDisplayName: (NSString *) newDisplayName - inContainer: (SOGoObject *) newContainer; ++ (id) folderWithName: (NSString *) aName + andDisplayName: (NSString *) aDisplayName + inContainer: (id) aContainer; +- (id) initWithName: (NSString *) newName + andDisplayName: (NSString *) newDisplayName + inContainer: (id) newContainer; - (void) setLDAPSource: (LDAPSource *) newLdapSource; @end diff --git a/SoObjects/Contacts/SOGoContactLDAPFolder.m b/SoObjects/Contacts/SOGoContactLDAPFolder.m index 2704be332..841a79a00 100644 --- a/SoObjects/Contacts/SOGoContactLDAPFolder.m +++ b/SoObjects/Contacts/SOGoContactLDAPFolder.m @@ -41,11 +41,11 @@ @implementation SOGoContactLDAPFolder -+ (id ) contactFolderWithName: (NSString *) aName - andDisplayName: (NSString *) aDisplayName - inContainer: (SOGoObject *) aContainer ++ (id) folderWithName: (NSString *) aName + andDisplayName: (NSString *) aDisplayName + inContainer: (id) aContainer { - SOGoContactLDAPFolder *folder; + id folder; folder = [[self alloc] initWithName: aName andDisplayName: aDisplayName @@ -68,9 +68,9 @@ return self; } -- (id ) initWithName: (NSString *) newName - andDisplayName: (NSString *) newDisplayName - inContainer: (SOGoObject *) newContainer +- (id) initWithName: (NSString *) newName + andDisplayName: (NSString *) newDisplayName + inContainer: (id) newContainer { if ((self = [self initWithName: newName inContainer: newContainer])) diff --git a/SoObjects/SOGo/GNUmakefile b/SoObjects/SOGo/GNUmakefile index f8a602b73..d2b9d3568 100644 --- a/SoObjects/SOGo/GNUmakefile +++ b/SoObjects/SOGo/GNUmakefile @@ -21,8 +21,9 @@ FHS_HEADER_DIRS = SOGo libSOGo_HEADER_FILES = \ SOGoObject.h \ - SOGoFolder.h \ SOGoContentObject.h \ + SOGoFolder.h \ + SOGoParentFolder.h \ SOGoUserFolder.h \ SOGoGroupsFolder.h \ SOGoGroupFolder.h \ @@ -50,8 +51,9 @@ libSOGo_HEADER_FILES = \ libSOGo_OBJC_FILES = \ SOGoObject.m \ - SOGoFolder.m \ SOGoContentObject.m \ + SOGoFolder.m \ + SOGoParentFolder.m \ SOGoUserFolder.m \ SOGoGroupsFolder.m \ SOGoGroupFolder.m \ diff --git a/SoObjects/SOGo/SOGoFolder.h b/SoObjects/SOGo/SOGoFolder.h index 5358299d3..dad4629ad 100644 --- a/SoObjects/SOGo/SOGoFolder.h +++ b/SoObjects/SOGo/SOGoFolder.h @@ -43,7 +43,8 @@ @interface SOGoFolder : SOGoObject { - NSString *ocsPath; + NSString *displayName; + NSString *ocsPath; GCSFolder *ocsFolder; NSMutableDictionary *aclCache; } @@ -52,6 +53,15 @@ /* accessors */ ++ (id) folderWithName: (NSString *) aName + andDisplayName: (NSString *) aDisplayName + inContainer: (id) aContainer; +- (id) initWithName: (NSString *) aName + andDisplayName: (NSString *) aDisplayName + inContainer: (id) aContainer; + +- (NSString *) displayName; + - (void) setOCSPath: (NSString *)_Path; - (NSString *) ocsPath; diff --git a/SoObjects/SOGo/SOGoFolder.m b/SoObjects/SOGo/SOGoFolder.m index 20a3b8944..18d2d4856 100644 --- a/SoObjects/SOGo/SOGoFolder.m +++ b/SoObjects/SOGo/SOGoFolder.m @@ -29,6 +29,7 @@ #import #import +#import #import #import #import @@ -85,14 +86,30 @@ static NSString *defaultUserID = @""; } sequence++; f = [[NSDate date] timeIntervalSince1970]; + return [NSString stringWithFormat:@"%0X-%0X-%0X-%0X", - pid, *(int *)&f, sequence++, random]; + pid, (int) f, sequence++, random]; +} + ++ (id) folderWithName: (NSString *) aName + andDisplayName: (NSString *) aDisplayName + inContainer: (id) aContainer +{ + id newFolder; + + newFolder = [[self alloc] initWithName: aName + andDisplayName: aDisplayName + inContainer: aContainer]; + [newFolder autorelease]; + + return newFolder; } - (id) init { if ((self = [super init])) { + displayName = nil; ocsPath = nil; ocsFolder = nil; aclCache = [NSMutableDictionary new]; @@ -101,11 +118,23 @@ static NSString *defaultUserID = @""; return self; } +- (id) initWithName: (NSString *) aName + andDisplayName: (NSString *) aDisplayName + inContainer: (id) aContainer +{ + if ((self = [self initWithName: aName + inContainer: aContainer])) + ASSIGN (displayName, aDisplayName); + + return self; +} + - (void) dealloc { [ocsFolder release]; [ocsPath release]; [aclCache release]; + [displayName release]; [super dealloc]; } @@ -154,6 +183,11 @@ static NSString *defaultUserID = @""; return NO; } +- (NSString *) displayName +{ + return displayName; +} + - (GCSFolder *) ocsFolder { GCSFolder *folder; @@ -196,7 +230,15 @@ static NSString *defaultUserID = @""; - (NSException *) delete { - return [[self folderManager] deleteFolderAtPath: ocsPath]; + NSException *error; + + if ([nameInContainer isEqualToString: @"personal"]) + error = [NSException exceptionWithHTTPStatus: 403 + reason: @"the 'personal' folder cannot be deleted"]; + else + error = [[self folderManager] deleteFolderAtPath: ocsPath]; + + return error; } - (NSArray *) fetchContentObjectNames diff --git a/SoObjects/SOGo/SOGoParentFolder.h b/SoObjects/SOGo/SOGoParentFolder.h new file mode 100644 index 000000000..5bbde0bc6 --- /dev/null +++ b/SoObjects/SOGo/SOGoParentFolder.h @@ -0,0 +1,50 @@ +/* SOGoParentFolder.h - this file is part of SOGo + * + * Copyright (C) 2006, 2007 Inverse groupe conseil + * + * Author: Wolfgang Sourdeau + * + * This file is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2, or (at your option) + * any later version. + * + * This file is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; see the file COPYING. If not, write to + * the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, USA. + */ + +#ifndef SOGOPARENTFOLDERS_H +#define SOGOPARENTFOLDERS_H + +#import "SOGoObject.h" + +@class NSMutableDictionary; +@class NSString; +@class WOResponse; + +@interface SOGoParentFolder : SOGoObject +{ + NSMutableDictionary *subFolders; + NSString *OCSPath; + Class subFolderClass; +} + ++ (NSString *) gcsFolderType; ++ (Class) subFolderClass; + +- (void) setBaseOCSPath: (NSString *) newOCSPath; + +- (NSArray *) subFolders; + +- (NSException *) newFolderWithName: (NSString *) name; + +@end + +#endif /* SOGOPARENTFOLDERS_H */ diff --git a/SoObjects/SOGo/SOGoParentFolder.m b/SoObjects/SOGo/SOGoParentFolder.m new file mode 100644 index 000000000..2bd1f6963 --- /dev/null +++ b/SoObjects/SOGo/SOGoParentFolder.m @@ -0,0 +1,240 @@ +/* SOGoParentFolder.m - this file is part of SOGo + * + * Copyright (C) 2006, 2007 Inverse groupe conseil + * + * Author: Wolfgang Sourdeau + * + * This file is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2, or (at your option) + * any later version. + * + * This file is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; see the file COPYING. If not, write to + * the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, USA. + */ + +#import +#import + +#import +#import +#import +#import +#import + +#import "SOGoFolder.h" + +#import "SOGoParentFolder.h" + +@implementation SOGoParentFolder + +- (id) init +{ + if ((self = [super init])) + { + subFolders = nil; + OCSPath = nil; + subFolderClass = Nil; + } + + return self; +} + +- (void) dealloc +{ + [subFolders release]; + [OCSPath release]; + [super dealloc]; +} + ++ (Class) subFolderClass +{ + [self subclassResponsibility: _cmd]; + + return Nil; +} + ++ (NSString *) gcsFolderType +{ + [self subclassResponsibility: _cmd]; + + return nil; +} + +- (void) setBaseOCSPath: (NSString *) newOCSPath +{ + ASSIGN (OCSPath, newOCSPath); +} + +- (void) _fetchPersonalFolders: (NSString *) sql + withChannel: (EOAdaptorChannel *) fc +{ + NSArray *attrs; + NSDictionary *row; + SOGoFolder *folder; + BOOL hasPersonal; + NSString *key, *path; + + if (!subFolderClass) + subFolderClass = [[self class] subFolderClass]; + + hasPersonal = NO; + [fc evaluateExpressionX: sql]; + attrs = [fc describeResults: NO]; + row = [fc fetchAttributes: attrs withZone: NULL]; + while (row) + { + folder + = [subFolderClass folderWithName: [row objectForKey: @"c_path4"] + andDisplayName: [row objectForKey: @"c_foldername"] + inContainer: self]; + key = [row objectForKey: @"c_path4"]; + hasPersonal = (hasPersonal || [key isEqualToString: @"personal"]); + [folder setOCSPath: [NSString stringWithFormat: @"%@/%@", + OCSPath, key]]; + [subFolders setObject: folder forKey: key]; + row = [fc fetchAttributes: attrs withZone: NULL]; + } + + if (!hasPersonal) + { + folder = [subFolderClass folderWithName: @"personal" + andDisplayName: @"personal" + inContainer: self]; + path = [NSString stringWithFormat: @"/Users/%@/%@/personal", + [self ownerInContext: context], + nameInContainer]; + [folder setOCSPath: path]; + [subFolders setObject: folder forKey: @"personal"]; + } +} + +- (void) appendPersonalSources +{ + GCSChannelManager *cm; + EOAdaptorChannel *fc; + NSURL *folderLocation; + NSString *sql, *gcsFolderType; + + cm = [GCSChannelManager defaultChannelManager]; + folderLocation + = [[GCSFolderManager defaultFolderManager] folderInfoLocation]; + fc = [cm acquireOpenChannelForURL: folderLocation]; + if (fc) + { + gcsFolderType = [[self class] gcsFolderType]; + + sql + = [NSString stringWithFormat: (@"SELECT c_path4, c_foldername FROM %@" + @" WHERE c_path2 = '%@'" + @" AND c_folder_type = '%@'"), + [folderLocation gcsTableName], + [self ownerInContext: context], + gcsFolderType]; + [self _fetchPersonalFolders: sql withChannel: fc]; + [cm releaseChannel: fc]; +// sql = [sql stringByAppendingFormat:@" WHERE %@ = '%@'", +// uidColumnName, [self uid]]; + } +} + +- (void) appendSystemSources +{ +} + +- (NSException *) newFolderWithName: (NSString *) name +{ + SOGoFolder *newFolder; + NSException *error; + + if (!subFolderClass) + subFolderClass = [[self class] subFolderClass]; + + newFolder = [subFolderClass folderWithName: name + andDisplayName: name + inContainer: self]; + if ([newFolder isKindOfClass: [NSException class]]) + error = (NSException *) newFolder; + else + { + [newFolder setOCSPath: [NSString stringWithFormat: @"%@/%@", + OCSPath, name]]; + if ([newFolder create]) + error = nil; + else + error = [NSException exceptionWithHTTPStatus: 400 + reason: @"The new folder could not be created"]; + } + + return error; +} + +- (void) initSubFolders +{ + if (!subFolders) + { + subFolders = [NSMutableDictionary new]; + [self appendPersonalSources]; + [self appendSystemSources]; + } +} + +- (id) lookupName: (NSString *) name + inContext: (WOContext *) lookupContext + acquire: (BOOL) acquire +{ + id obj; + + /* first check attributes directly bound to the application */ + obj = [super lookupName: name inContext: lookupContext acquire: NO]; + if (!obj) + { + if (!subFolders) + [self initSubFolders]; + + obj = [subFolders objectForKey: name]; + } + + return obj; +} + +- (NSArray *) toManyRelationshipKeys +{ + if (!subFolders) + [self initSubFolders]; + + return [subFolders allKeys]; +} + +- (NSArray *) subFolders +{ + if (!subFolders) + [self initSubFolders]; + + return [subFolders allValues]; +} + +/* acls */ +- (NSArray *) aclsForUser: (NSString *) uid +{ + return nil; +} + +- (BOOL) davIsCollection +{ + return YES; +} + +- (NSString *) davContentType +{ + return @"httpd/unix-directory"; +} + +@end diff --git a/UI/Common/UIxFolderActions.m b/UI/Common/UIxFolderActions.m index ca14b9d5e..b7a469a00 100644 --- a/UI/Common/UIxFolderActions.m +++ b/UI/Common/UIxFolderActions.m @@ -37,6 +37,8 @@ #import #import +#import "WODirectAction+SOGo.h" + #import "UIxFolderActions.h" @implementation UIxFolderActions @@ -89,10 +91,9 @@ NSMutableDictionary *folderSubscription; NSString *mailInvitationURL; - response = [context response]; if ([owner isEqualToString: login]) { - [response setStatus: 403]; + response = [self responseWithStatus: 403]; [response appendContentString: @"You cannot (un)subscribe to a folder that you own!"]; } @@ -119,12 +120,12 @@ mailInvitationURL = [[clientObject soURLToBaseContainerForCurrentUser] absoluteString]; - [response setStatus: 302]; + response = [self responseWithStatus: 302]; [response setHeader: mailInvitationURL forKey: @"location"]; } else - [response setStatus: 204]; + response = [self responseWith204]; } return response; @@ -162,22 +163,14 @@ - (WOResponse *) canAccessContentAction { - WOResponse *response; - - response = [context response]; - [response setStatus: 204]; - - return response; + return [self responseWith204]; } - (WOResponse *) _realFolderActivation: (BOOL) makeActive { - WOResponse *response; NSMutableDictionary *folderSubscription, *folderDict; NSNumber *active; - response = [context response]; - [self _setupContext]; active = [NSNumber numberWithBool: makeActive]; if ([owner isEqualToString: login]) @@ -196,9 +189,8 @@ } [ud synchronize]; - [response setStatus: 204]; - return response; + return [self responseWith204]; } - (WOResponse *) activateFolderAction diff --git a/UI/Common/WODirectAction+SOGo.h b/UI/Common/WODirectAction+SOGo.h index 92ec03206..067046b69 100644 --- a/UI/Common/WODirectAction+SOGo.h +++ b/UI/Common/WODirectAction+SOGo.h @@ -30,6 +30,8 @@ @interface WODirectAction (SOGoExtension) +- (WOResponse *) responseWithStatus: (unsigned int) status; +- (WOResponse *) responseWith204; - (WOResponse *) redirectToLocation: (NSString *) newLocation; @end diff --git a/UI/Common/WODirectAction+SOGo.m b/UI/Common/WODirectAction+SOGo.m index ddeea2aaa..13c8b86d8 100644 --- a/UI/Common/WODirectAction+SOGo.m +++ b/UI/Common/WODirectAction+SOGo.m @@ -28,15 +28,30 @@ @implementation WODirectAction (SOGoExtension) -- (WOResponse *) redirectToLocation: (NSString *) newLocation +- (WOResponse *) responseWithStatus: (unsigned int) status { WOResponse *response; response = [context response]; - [response setStatus: 302 /* moved */]; + [response setStatus: status]; + + return response; +} + +- (WOResponse *) responseWith204 +{ + return [self responseWithStatus: 204]; +} + +- (WOResponse *) redirectToLocation: (NSString *) newLocation +{ + WOResponse *response; + + response = [self responseWithStatus: 302]; [response setHeader: newLocation forKey: @"location"]; return response; } + @end diff --git a/UI/Contacts/UIxContactFoldersView.m b/UI/Contacts/UIxContactFoldersView.m index 1509f4a52..fa47cb91e 100644 --- a/UI/Contacts/UIxContactFoldersView.m +++ b/UI/Contacts/UIxContactFoldersView.m @@ -52,8 +52,7 @@ WORequest *request; folders = [self clientObject]; - action = [NSString stringWithFormat: @"../%@/%@", - [folders defaultSourceName], + action = [NSString stringWithFormat: @"../personal/%@", actionName]; request = [[self context] request]; @@ -82,7 +81,11 @@ name = [self queryParameterForKey: @"name"]; if ([name length] > 0) - response = [[self clientObject] newFolderWithName: name]; + { + response = [[self clientObject] newFolderWithName: name]; + if (!response) + response = [self responseWith204]; + } else response = [NSException exceptionWithHTTPStatus: 400 reason: @"The name is missing"]; @@ -111,8 +114,7 @@ { uid = [currentContact objectForKey: @"c_uid"]; if (uid && ![results objectForKey: uid]) - [results setObject: currentContact - forKey: uid]; + [results setObject: currentContact forKey: uid]; currentContact = [folderResults nextObject]; } } @@ -202,7 +204,7 @@ gcsFolders = [NSMutableArray new]; [gcsFolders autorelease]; - contactSubfolders = [[contactFolders contactFolders] objectEnumerator]; + contactSubfolders = [[contactFolders subFolders] objectEnumerator]; currentContactFolder = [contactSubfolders nextObject]; while (currentContactFolder) { diff --git a/UI/Contacts/UIxContactsListViewContainer.m b/UI/Contacts/UIxContactsListViewContainer.m index 2bf4f0c09..5aab0c6d7 100644 --- a/UI/Contacts/UIxContactsListViewContainer.m +++ b/UI/Contacts/UIxContactsListViewContainer.m @@ -29,6 +29,7 @@ #import #import +#import #import "UIxContactsListViewContainer.h" @@ -115,7 +116,7 @@ folderContainer = [[self clientObject] container]; - return [folderContainer contactFolders]; + return [folderContainer subFolders]; } - (NSString *) currentContactFolderId diff --git a/UI/MailerUI/UIxMailAccountActions.m b/UI/MailerUI/UIxMailAccountActions.m index 004c3a634..7f3a66cb3 100644 --- a/UI/MailerUI/UIxMailAccountActions.m +++ b/UI/MailerUI/UIxMailAccountActions.m @@ -108,8 +108,7 @@ rawFolders = [co allFolderPaths]; folders = [self _jsonFolders: [rawFolders objectEnumerator]]; - response = [context response]; - [response setStatus: 200]; + response = [self responseWithStatus: 200]; [response setHeader: @"text/plain; charset=utf-8" forKey: @"content-type"]; [response appendContentString: [folders jsonRepresentation]]; diff --git a/UI/MailerUI/UIxMailActions.m b/UI/MailerUI/UIxMailActions.m index 42b5fa0e3..3ebf019c0 100644 --- a/UI/MailerUI/UIxMailActions.m +++ b/UI/MailerUI/UIxMailActions.m @@ -94,10 +94,7 @@ response = [[self clientObject] trashInContext: context]; if (!response) - { - response = [context response]; - [response setStatus: 204]; - } + response = [self responseWith204]; return response; } @@ -113,10 +110,7 @@ response = [[self clientObject] moveToFolderNamed: destinationFolder inContext: context]; if (!response) - { - response = [context response]; - [response setStatus: 204]; - } + response = [self responseWith204]; } else response = [NSException exceptionWithHTTPStatus: 500 /* Server Error */ @@ -125,6 +119,30 @@ return response; } +/* active message */ + +- (id) markMessageUnreadAction +{ + id response; + + response = [[self clientObject] removeFlags: @"seen"]; + if (!response) + response = [self responseWith204]; + + return response; +} + +- (id) markMessageReadAction +{ + id response; + + response = [[self clientObject] addFlags: @"seen"]; + if (!response) + response = [self responseWith204]; + + return response; +} + /* SOGoDraftObject */ - (WOResponse *) editAction { @@ -158,10 +176,7 @@ if (error) response = error; else - { - response = [context response]; - [response setStatus: 204]; - } + response = [self responseWith204]; return response; } @@ -171,17 +186,15 @@ WOResponse *response; NSString *filename; - response = [context response]; - filename = [[context request] formValueForKey: @"filename"]; if ([filename length] > 0) { + response = [self responseWith204]; [[self clientObject] deleteAttachmentWithName: filename]; - [response setStatus: 204]; } else { - [response setStatus: 500]; + response = [self responseWithStatus: 500]; [response appendContentString: @"How did you end up here?"]; } diff --git a/UI/MailerUI/UIxMailEditor.m b/UI/MailerUI/UIxMailEditor.m index 726b79709..d09189a6a 100644 --- a/UI/MailerUI/UIxMailEditor.m +++ b/UI/MailerUI/UIxMailEditor.m @@ -404,10 +404,7 @@ static NSArray *infoKeys = nil; { result = [[self clientObject] save]; if (!result) - { - result = [context response]; - [result setStatus: 204]; - } + result = [self responseWith204]; } else result = [self failedToSaveFormResponse]; diff --git a/UI/MailerUI/UIxMailFolderActions.m b/UI/MailerUI/UIxMailFolderActions.m index b4a184b84..84d7fa95e 100644 --- a/UI/MailerUI/UIxMailFolderActions.m +++ b/UI/MailerUI/UIxMailFolderActions.m @@ -36,6 +36,8 @@ #import #import +#import + #import "UIxMailFolderActions.h" @implementation UIxMailFolderActions @@ -49,7 +51,6 @@ NSString *folderName; co = [self clientObject]; - response = [context response]; folderName = [[context request] formValueForKey: @"name"]; if ([folderName length] > 0) @@ -58,15 +59,15 @@ error = [connection createMailbox: folderName atURL: [co imap4URL]]; if (error) { - [response setStatus: 500]; + response = [self responseWithStatus: 500]; [response appendContentString: @"Unable to create folder."]; } else - [response setStatus: 204]; + response = [self responseWith204]; } else { - [response setStatus: 500]; + response = [self responseWithStatus: 500]; [response appendContentString: @"Missing 'name' parameter."]; } @@ -100,7 +101,6 @@ NSURL *srcURL, *destURL; co = [self clientObject]; - response = [context response]; folderName = [[context request] formValueForKey: @"name"]; if ([folderName length] > 0) @@ -112,15 +112,15 @@ toURL: destURL]; if (error) { - [response setStatus: 500]; + response = [self responseWithStatus: 500]; [response appendContentString: @"Unable to rename folder."]; } else - [response setStatus: 204]; + response = [self responseWith204]; } else { - [response setStatus: 500]; + response = [self responseWithStatus: 500]; [response appendContentString: @"Missing 'name' parameter."]; } @@ -154,7 +154,6 @@ NSURL *srcURL, *destURL; co = [self clientObject]; - response = [context response]; connection = [co imap4Connection]; srcURL = [co imap4URL]; destURL = [self _trashedURLOfFolder: srcURL @@ -164,11 +163,11 @@ toURL: destURL]; if (error) { - [response setStatus: 500]; + response = [self responseWithStatus: 500]; [response appendContentString: @"Unable to move folder."]; } else - [response setStatus: 204]; + response = [self responseWith204]; return response; } @@ -180,18 +179,17 @@ WOResponse *response; co = [self clientObject]; - response = [context response]; error = [co expunge]; if (error) { - [response setStatus: 500]; + response = [self responseWithStatus: 500]; [response appendContentString: @"Unable to expunge folder."]; } else { [co flushMailCaches]; - [response setStatus: 204]; + response = [self responseWith204]; } return response; @@ -207,7 +205,6 @@ NSURL *currentURL; co = [self clientObject]; - response = [context response]; error = [co addFlagsToAllMessages: @"deleted"]; if (!error) @@ -226,11 +223,11 @@ } if (error) { - [response setStatus: 500]; + response = [self responseWithStatus: 500]; [response appendContentString: @"Unable to empty the trash folder."]; } else - [response setStatus: 204]; + response = [self responseWith204]; return response; } @@ -242,7 +239,6 @@ WOResponse *response; SOGoMailFolder *clientObject; - response = [context response]; mailInvitationParam = [[context request] formValueForKey: @"mail-invitation"]; if ([mailInvitationParam boolValue]) @@ -257,7 +253,7 @@ } else { - [response setStatus: 500]; + response = [self responseWithStatus: 500]; [response appendContentString: @"How did you end up here?"]; } @@ -283,8 +279,7 @@ NGImap4Client *client; NSString *responseString; - response = [context response]; - [response setStatus: 200]; + response = [self responseWithStatus: 200]; [response setHeader: @"text/plain; charset=UTF-8" forKey: @"content-type"]; diff --git a/UI/MailerUI/UIxMailListView.m b/UI/MailerUI/UIxMailListView.m index 46f7505e7..143707c93 100644 --- a/UI/MailerUI/UIxMailListView.m +++ b/UI/MailerUI/UIxMailListView.m @@ -221,10 +221,24 @@ static int attachmentFlagSize = 8096; - (NSArray *) sortedUIDs { + EOQualifier *fetchQualifier, *notDeleted; if (!sortedUIDs) { + notDeleted = [EOQualifier qualifierWithQualifierFormat: + @"(not (flags = %@))", + @"deleted"]; + if (qualifier) + { + fetchQualifier = [[EOAndQualifier alloc] initWithQualifiers: + notDeleted, qualifier, + nil]; + [fetchQualifier autorelease]; + } + else + fetchQualifier = notDeleted; + sortedUIDs - = [[self clientObject] fetchUIDsMatchingQualifier: qualifier + = [[self clientObject] fetchUIDsMatchingQualifier: fetchQualifier sortOrdering: [self imap4SortOrdering]]; [sortedUIDs retain]; } @@ -407,36 +421,8 @@ static int attachmentFlagSize = 8096; return [self redirectToLocation:url]; } -/* active message */ - -- (SOGoMailObject *) lookupActiveMessage -{ - NSString *uid; - - if ((uid = [[context request] formValueForKey: @"uid"]) == nil) - return nil; - - return [[self clientObject] lookupName: uid - inContext: context - acquire: NO]; -} - /* actions */ -- (BOOL) isJavaScriptRequest -{ - return [[[context request] formValueForKey:@"jsonly"] boolValue]; -} - -- (id) javaScriptOK -{ - WOResponse *r; - - r = [context response]; - [r setStatus:200 /* OK */]; - return r; -} - - (int) firstMessageOfPageFor: (int) messageNbr { NSArray *messageNbrs; @@ -462,8 +448,7 @@ static int attachmentFlagSize = 8096; if ([criteria isEqualToString: @"subject"]) qualifier = [EOQualifier qualifierWithQualifierFormat: - @"(subject doesContain: %@)", - value]; + @"(subject doesContain: %@)", value]; else if ([criteria isEqualToString: @"sender"]) qualifier = [EOQualifier qualifierWithQualifierFormat: @"(sender doesContain: %@)", value]; @@ -510,39 +495,6 @@ static int attachmentFlagSize = 8096; return self; } -- (id) viewAction -{ - return [self defaultAction]; -} - -- (id) markMessageUnreadAction -{ - NSException *error; - - if ((error = [[self lookupActiveMessage] removeFlags:@"seen"]) != nil) - // TODO: improve error handling - return error; - - if ([self isJavaScriptRequest]) - return [self javaScriptOK]; - - return [self redirectToLocation:@"view"]; -} - -- (id) markMessageReadAction -{ - NSException *error; - - if ((error = [[self lookupActiveMessage] addFlags:@"seen"]) != nil) - // TODO: improve error handling - return error; - - if ([self isJavaScriptRequest]) - return [self javaScriptOK]; - - return [self redirectToLocation:@"view"]; -} - - (id) getMailAction { // TODO: we might want to flush the caches? diff --git a/UI/MailerUI/UIxMailSourceView.m b/UI/MailerUI/UIxMailSourceView.m index c0586221d..60976e53d 100644 --- a/UI/MailerUI/UIxMailSourceView.m +++ b/UI/MailerUI/UIxMailSourceView.m @@ -25,6 +25,8 @@ #import #import +#import + #import "UIxMailSourceView.h" @implementation UIxMailSourceView @@ -36,8 +38,7 @@ source = [[self clientObject] contentAsString]; - response = [context response]; - [response setStatus: 200]; + response = [self responseWithStatus: 200]; [response setHeader: @"text/plain; charset=utf-8" forKey: @"content-type"]; [response appendContentString: source]; diff --git a/UI/MailerUI/UIxMailView.m b/UI/MailerUI/UIxMailView.m index 107e9c2ad..e3da019f6 100644 --- a/UI/MailerUI/UIxMailView.m +++ b/UI/MailerUI/UIxMailView.m @@ -142,37 +142,42 @@ static NSString *mailETag = nil; - (id) defaultAction { + WOResponse *response; + NSString *s; + /* check etag to see whether we really must rerender */ - if (mailETag != nil ) { - /* - Note: There is one thing which *can* change for an existing message, - those are the IMAP4 flags (and annotations, which we do not use). - Since we don't render the flags, it should be OK, if this changes - we must embed the flagging into the etag. - */ - NSString *s; - - if ((s = [[context request] headerForKey:@"if-none-match"])) { - if ([s rangeOfString:mailETag].length > 0) { /* not perfectly correct */ - /* client already has the proper entity */ - // [self logWithFormat:@"MATCH: %@ (tag %@)", s, mailETag]; - - if (![[self clientObject] doesMailExist]) { - return [NSException exceptionWithHTTPStatus:404 /* Not Found */ - reason:@"message got deleted"]; + if (mailETag) + { + /* + Note: There is one thing which *can* change for an existing message, + those are the IMAP4 flags (and annotations, which we do not use). + Since we don't render the flags, it should be OK, if this changes + we must embed the flagging into the etag. + */ + s = [[context request] headerForKey: @"if-none-match"]; + if (s) + { + if ([s rangeOfString:mailETag].length > 0) /* not perfectly correct */ + { + /* client already has the proper entity */ + // [self logWithFormat:@"MATCH: %@ (tag %@)", s, mailETag]; + + if (![[self clientObject] doesMailExist]) { + return [NSException exceptionWithHTTPStatus:404 /* Not Found */ + reason:@"message got deleted"]; + } + + response = [context response]; + [response setStatus: 304 /* Not Modified */]; + + return response; + } } - - [[context response] setStatus:304 /* Not Modified */]; - return [context response]; - } } - } - if ([self message] == nil) { - // TODO: redirect to proper error + if (![self message]) // TODO: redirect to proper error return [NSException exceptionWithHTTPStatus:404 /* Not Found */ reason:@"did not find specified message!"]; - } return self; } diff --git a/UI/MailerUI/product.plist b/UI/MailerUI/product.plist index d6806567c..73ed08099 100644 --- a/UI/MailerUI/product.plist +++ b/UI/MailerUI/product.plist @@ -115,16 +115,6 @@ protectedBy = "View"; pageName = "UIxMailListView"; }; - markMessageUnread = { - protectedBy = "View"; - pageName = "UIxMailListView"; - actionName = "markMessageUnread"; - }; - markMessageRead = { - protectedBy = "View"; - pageName = "UIxMailListView"; - actionName = "markMessageRead"; - }; getMail = { protectedBy = "View"; pageName = "UIxMailListView"; @@ -235,6 +225,16 @@ actionClass = "UIxMailActions"; actionName = "forward"; }; + markMessageUnread = { + protectedBy = "View"; + actionClass = "UIxMailActions"; + actionName = "markMessageUnread"; + }; + markMessageRead = { + protectedBy = "View"; + actionClass = "UIxMailActions"; + actionName = "markMessageRead"; + }; }; }; diff --git a/UI/MainUI/SOGoRootPage.m b/UI/MainUI/SOGoRootPage.m index c88e9af4f..d4bdc2070 100644 --- a/UI/MainUI/SOGoRootPage.m +++ b/UI/MainUI/SOGoRootPage.m @@ -69,7 +69,7 @@ auth = [[WOApplication application] authenticatorInContext: context]; - response = [context response]; + response = [self responseWith204]; cookieString = [NSString stringWithFormat: @"%@:%@", [self queryParameterForKey: @"userName"], [self queryParameterForKey: @"password"]]; @@ -78,7 +78,6 @@ authCookie = [WOCookie cookieWithName: [auth cookieNameInContext: context] value: cookieValue]; [authCookie setPath: @"/"]; - [response setStatus: 204]; [response addCookie: authCookie]; return response; diff --git a/UI/SOGoUI/UIxComponent.h b/UI/SOGoUI/UIxComponent.h index 4435c7303..f0c019083 100644 --- a/UI/SOGoUI/UIxComponent.h +++ b/UI/SOGoUI/UIxComponent.h @@ -68,25 +68,25 @@ /* date selection */ - (NSCalendarDate *) selectedDate; -- (NSString *)dateStringForDate:(NSCalendarDate *)_date; +- (NSString *) dateStringForDate: (NSCalendarDate *)_date; - (BOOL) hideFrame; - (UIxComponent *) jsCloseWithRefreshMethod: (NSString *) methodName; /* SoUser */ -- (NSString *)shortUserNameForDisplay; +- (NSString *) shortUserNameForDisplay; /* labels */ -- (NSString *)labelForKey:(NSString *)_key; +- (NSString *) labelForKey:(NSString *)_key; -- (NSString *)localizedNameForDayOfWeek:(unsigned)_dayOfWeek; -- (NSString *)localizedAbbreviatedNameForDayOfWeek:(unsigned)_dayOfWeek; -- (NSString *)localizedNameForMonthOfYear:(unsigned)_monthOfYear; -- (NSString *)localizedAbbreviatedNameForMonthOfYear:(unsigned)_monthOfYear; +- (NSString *) localizedNameForDayOfWeek:(unsigned)_dayOfWeek; +- (NSString *) localizedAbbreviatedNameForDayOfWeek:(unsigned)_dayOfWeek; +- (NSString *) localizedNameForMonthOfYear:(unsigned)_monthOfYear; +- (NSString *) localizedAbbreviatedNameForMonthOfYear:(unsigned)_monthOfYear; /* HTTP method safety */ -- (BOOL)isInvokedBySafeMethod; +- (BOOL) isInvokedBySafeMethod; /* locale */ - (NSDictionary *)locale; @@ -95,6 +95,8 @@ - (WOResourceManager *) pageResourceManager; - (NSString *) urlForResourceFilename: (NSString *) filename; +- (WOResponse *) responseWith204; + /* Debugging */ - (BOOL)isUIxDebugEnabled; diff --git a/UI/SOGoUI/UIxComponent.m b/UI/SOGoUI/UIxComponent.m index 95e48cf94..643dca563 100644 --- a/UI/SOGoUI/UIxComponent.m +++ b/UI/SOGoUI/UIxComponent.m @@ -400,7 +400,7 @@ static BOOL uixDebugEnabled = NO; userTimeZone = [[context activeUser] timeZone]; [_date setTimeZone: userTimeZone]; - return [_date descriptionWithCalendarFormat:@"%Y%m%d"]; + return [_date descriptionWithCalendarFormat: @"%Y%m%d"]; } - (BOOL) hideFrame @@ -569,6 +569,16 @@ static BOOL uixDebugEnabled = NO; return url; } +- (WOResponse *) responseWith204 +{ + WOResponse *response; + + response = [context response]; + [response setStatus: 204]; + + return response; +} + /* debugging */ - (BOOL)isUIxDebugEnabled { diff --git a/UI/Scheduler/UIxCalListingActions.m b/UI/Scheduler/UIxCalListingActions.m index 03f647f9d..34a1ec92d 100644 --- a/UI/Scheduler/UIxCalListingActions.m +++ b/UI/Scheduler/UIxCalListingActions.m @@ -39,6 +39,8 @@ #import #import +#import + #import "NSArray+Scheduler.h" #import "UIxCalListingActions.h" @@ -289,10 +291,9 @@ { WOResponse *response; - response = [context response]; + response = [self responseWithStatus: 200]; [response setHeader: @"text/plain; charset=utf-8" forKey: @"content-type"]; - [response setStatus: 200]; [response appendContentString: [data jsonRepresentation]]; return response; diff --git a/UI/Templates/MailerUI/UIxMailListView.wox b/UI/Templates/MailerUI/UIxMailListView.wox index b6514b3a7..c5a3f0de0 100644 --- a/UI/Templates/MailerUI/UIxMailListView.wox +++ b/UI/Templates/MailerUI/UIxMailListView.wox @@ -63,7 +63,6 @@ var:class="messageSubjectCellStyleClass" var:id="msgDivID" >