diff --git a/.gitignore b/.gitignore index a8f9ddee4..5123e76a3 100644 --- a/.gitignore +++ b/.gitignore @@ -1,5 +1,6 @@ config.make tags +*._* */obj/ *._* */*/obj/ diff --git a/SoObjects/Contacts/English.lproj/Localizable.strings b/SoObjects/Contacts/English.lproj/Localizable.strings index 56404b013..0d040749c 100644 --- a/SoObjects/Contacts/English.lproj/Localizable.strings +++ b/SoObjects/Contacts/English.lproj/Localizable.strings @@ -1 +1,2 @@ "Personal Address Book" = "Personal Address Book"; +"Collected Address Book" = "Collected Address Book"; diff --git a/SoObjects/Contacts/French.lproj/Localizable.strings b/SoObjects/Contacts/French.lproj/Localizable.strings index af4d87c3a..2b0358694 100644 --- a/SoObjects/Contacts/French.lproj/Localizable.strings +++ b/SoObjects/Contacts/French.lproj/Localizable.strings @@ -1 +1,2 @@ "Personal Address Book" = "Carnet d'adresses personnel"; +"Collected Address Book" = "Carnet d'adresses collectés"; diff --git a/SoObjects/Contacts/SOGoContactFolders.h b/SoObjects/Contacts/SOGoContactFolders.h index 1b685c85b..bb984f0b6 100644 --- a/SoObjects/Contacts/SOGoContactFolders.h +++ b/SoObjects/Contacts/SOGoContactFolders.h @@ -25,12 +25,19 @@ @interface SOGoContactFolders : SOGoParentFolder +- (NSString *) defaultFolderName; +- (NSString *) collectedFolderName; + - (NSException *) renameLDAPAddressBook: (NSString *) sourceID withDisplayName: (NSString *) newDisplayName; - (NSException *) removeLDAPAddressBook: (NSString *) sourceID; - (NSDictionary *) systemSources; +- (NSArray *) allContactsFromFilter: (NSString *) theFilter + excludeGroups: (BOOL) excludeGroups + excludeLists: (BOOL) excludeLists; + @end #endif /* SOGOCONTACTFOLDERS_H */ diff --git a/SoObjects/Contacts/SOGoContactFolders.m b/SoObjects/Contacts/SOGoContactFolders.m index 3c3e938f0..b0428f7f4 100644 --- a/SoObjects/Contacts/SOGoContactFolders.m +++ b/SoObjects/Contacts/SOGoContactFolders.m @@ -22,12 +22,18 @@ #import #import #import +#import #import #import #import #import +#import +#import +#import +#import + #import #import #import @@ -40,10 +46,17 @@ #import "SOGoContactFolders.h" +Class SOGoContactSourceFolderK; + #define XMLNS_INVERSEDAV @"urn:inverse:params:xml:ns:inverse-dav" @implementation SOGoContactFolders ++ (void) initialize +{ + SOGoContactSourceFolderK = [SOGoContactSourceFolder class]; +} + + (NSString *) gcsFolderType { return @"Contact"; @@ -110,6 +123,38 @@ return result; } +- (NSException *) appendCollectedSources +{ + GCSChannelManager *cm; + EOAdaptorChannel *fc; + NSURL *folderLocation; + NSString *sql, *gcsFolderType; + NSException *error; + + cm = [GCSChannelManager defaultChannelManager]; + folderLocation = [[GCSFolderManager defaultFolderManager] folderInfoLocation]; + fc = [cm acquireOpenChannelForURL: folderLocation]; + if ([fc isOpen]) + { + gcsFolderType = [[self class] gcsFolderType]; + + sql = [NSString stringWithFormat: (@"SELECT c_path4 FROM %@" + @" WHERE c_path2 = '%@'" + @" AND c_folder_type = '%@'"), + [folderLocation gcsTableName], owner, gcsFolderType]; + + error = [super fetchSpecialFolders: sql withChannel: fc andFolderType: SOGoCollectedFolder]; + + [cm releaseChannel: fc]; + } + else + error = [NSException exceptionWithName: @"SOGoDBException" + reason: @"database connection could not be open" + userInfo: nil]; + + return error; +} + - (NSDictionary *) systemSources { NSMutableDictionary *systemSources; @@ -225,7 +270,7 @@ if ([sourceID isEqualToString: @"personal"]) result = [NSException exceptionWithHTTPStatus: 403 - reason: @"folder 'personal' cannot be deleted"]; + reason: (@"folder '%@' cannot be deleted", sourceID)]; else { result = nil; @@ -250,6 +295,11 @@ return [self labelForKey: @"Personal Address Book"]; } +- (NSString *) collectedFolderName +{ + return [self labelForKey: @"Collected Address Book"]; +} + - (NSArray *) toManyRelationshipKeys { NSMutableArray *keys; @@ -371,4 +421,89 @@ asWebDAVValue]; } +- (NSArray *) allContactsFromFilter: (NSString *) theFilter + excludeGroups: (BOOL) excludeGroups + excludeLists: (BOOL) excludeLists +{ + SOGoFolder *folder; + NSString *mail, *domain; + NSArray *folders, *contacts, *descriptors, *sortedContacts; + NSMutableArray *sortedFolders; + NSMutableDictionary *contact, *uniqueContacts; + unsigned int i, j, max; + NSSortDescriptor *commonNameDescriptor; + + // NSLog(@"Search all contacts: %@", searchText); + + domain = [[context activeUser] domain]; + folders = nil; + NS_DURING + folders = [self subFolders]; + NS_HANDLER + /* We need to specifically test for @"SOGoDBException", which is + raised explicitly in SOGoParentFolder. Any other exception should + be re-raised. */ + if ([[localException name] isEqualToString: @"SOGoDBException"]) + folders = nil; + else + [localException raise]; + NS_ENDHANDLER; + max = [folders count]; + sortedFolders = [NSMutableArray arrayWithCapacity: max]; + uniqueContacts = [NSMutableDictionary dictionary]; + for (i = 0; i < max; i++) + { + folder = [folders objectAtIndex: i]; + /* We first search in LDAP folders (in case of duplicated entries in GCS folders) */ + if ([folder isKindOfClass: SOGoContactSourceFolderK]) + [sortedFolders insertObject: folder atIndex: 0]; + else + [sortedFolders addObject: folder]; + } + for (i = 0; i < max; i++) + { + folder = [sortedFolders objectAtIndex: i]; + //NSLog(@" Address book: %@ (%@)", [folder displayName], [folder class]); + contacts = [folder lookupContactsWithFilter: theFilter + onCriteria: @"name_or_address" + sortBy: @"c_cn" + ordering: NSOrderedAscending + inDomain: domain]; + for (j = 0; j < [contacts count]; j++) + { + contact = [contacts objectAtIndex: j]; + mail = [contact objectForKey: @"c_mail"]; + //NSLog(@" found %@ (%@) ? %@", [contact objectForKey: @"c_name"], mail, + // [contact description]); + if (!excludeLists && [[contact objectForKey: @"c_component"] + isEqualToString: @"vlist"]) + { + [contact setObject: [folder nameInContainer] + forKey: @"container"]; + [uniqueContacts setObject: contact + forKey: [contact objectForKey: @"c_name"]]; + } + else if ([mail length] + && [uniqueContacts objectForKey: mail] == nil + && !(excludeGroups && [contact objectForKey: @"isGroup"])) + [uniqueContacts setObject: contact forKey: mail]; + } + } + if ([uniqueContacts count] > 0) + { + // Sort the contacts by display name + commonNameDescriptor = [[NSSortDescriptor alloc] initWithKey: @"c_cn" + ascending:YES]; + descriptors = [NSArray arrayWithObjects: commonNameDescriptor, nil]; + [commonNameDescriptor release]; + sortedContacts = [[uniqueContacts allValues] + sortedArrayUsingDescriptors: descriptors]; + } + else + sortedContacts = [NSArray array]; + + return sortedContacts; +} + + @end diff --git a/SoObjects/Mailer/SOGoDraftObject.h b/SoObjects/Mailer/SOGoDraftObject.h index 94c5d2888..4004d32a9 100644 --- a/SoObjects/Mailer/SOGoDraftObject.h +++ b/SoObjects/Mailer/SOGoDraftObject.h @@ -102,6 +102,8 @@ - (NSData *) mimeMessageAsData; /* operations */ +- (NSArray *) allRecipients; +- (NSArray *) allBareRecipients; - (NSException *) delete; - (NSException *) sendMail; diff --git a/SoObjects/Mailer/SOGoDraftObject.m b/SoObjects/Mailer/SOGoDraftObject.m index bd5a0d469..1f1391ef7 100644 --- a/SoObjects/Mailer/SOGoDraftObject.m +++ b/SoObjects/Mailer/SOGoDraftObject.m @@ -45,6 +45,7 @@ #import #import #import +#import #import #import #import @@ -63,6 +64,11 @@ #import #import +#import + +#import +#import + #import "NSData+Mail.h" #import "NSString+Mail.h" #import "SOGoMailAccount.h" @@ -1660,7 +1666,7 @@ static NSString *userAgent = nil; { recipients = [headers objectForKey: fieldNames[count]]; if ([recipients count] > 0) - [allRecipients addObjectsFromArray: recipients]; + [allRecipients addObjectsFromArray: recipients]; } return allRecipients; @@ -1689,6 +1695,64 @@ static NSString *userAgent = nil; // - (NSException *) sendMail { + SOGoUserDefaults *ud; + ud = [[context activeUser] userDefaults]; + + if ([ud mailAddOutgoingAddresses]) + { + SOGoContactFolders *contactFolders; + NGMailAddressParser *parser; + id parsedRecipient; + SOGoContactFolder *folder; + SOGoContactGCSEntry *newContact; + NGVCard *card; + Class contactGCSEntry; + NSMutableArray *recipients; + NSString *recipient, *emailAddress, *displayName, *addressBook, *uid; + NSArray *matchingContacts; + int i; + + // Get all the addressbooks + contactFolders = [[[context activeUser] homeFolderInContext: context] + lookupName: @"Contacts" + inContext: context + acquire: NO]; + // Get all the recipients from the current email + recipients = [self allRecipients]; + for (i = 0; i < [recipients count]; i++) + { + // The address contains a string. ex: "John Doe " + recipient = [recipients objectAtIndex: i]; + parser = [NGMailAddressParser mailAddressParserWithString: recipient]; + parsedRecipient = [parser parse]; + emailAddress = [parsedRecipient address]; + displayName = [parsedRecipient displayName]; + + matchingContacts = [contactFolders allContactsFromFilter: emailAddress + excludeGroups: YES + excludeLists: YES]; + } + // If we don't get any results from the autocompletion code, we add it.. + if ([matchingContacts count] == 0) + { + /* Get the selected addressbook from the user preferences where the new address will be added */ + addressBook = [ud selectedAddressBook]; + folder = [contactFolders lookupName: addressBook inContext: context acquire: NO]; + uid = [folder globallyUniqueObjectId]; + + if (folder && uid) + { + card = [NGVCard cardWithUid: uid]; + [card addEmail: emailAddress types: nil]; + + contactGCSEntry = NSClassFromString(@"SOGoContactGCSEntry"); + newContact = [contactGCSEntry objectWithName: uid + inContainer: folder]; + [newContact setIsNew: YES]; + [newContact saveContentString: [card versitString]]; + } + } + } return [self sendMailAndCopyToSent: YES]; } diff --git a/SoObjects/SOGo/SOGoConstants.h b/SoObjects/SOGo/SOGoConstants.h index 433760346..830d2bea4 100644 --- a/SoObjects/SOGo/SOGoConstants.h +++ b/SoObjects/SOGo/SOGoConstants.h @@ -51,4 +51,10 @@ typedef enum EventUpdated = 2, } SOGoEventOperation; +typedef enum +{ + SOGoPersonalFolder = 0, + SOGoCollectedFolder = 1, +} SOGoFolderType; + #endif /* _SOGOCONSTANTS_H_ */ diff --git a/SoObjects/SOGo/SOGoDefaults.plist b/SoObjects/SOGo/SOGoDefaults.plist index 7ff98c36c..649d151d1 100644 --- a/SoObjects/SOGo/SOGoDefaults.plist +++ b/SoObjects/SOGo/SOGoDefaults.plist @@ -54,6 +54,7 @@ SOGoIMAPServer = "localhost"; SOGoMailDomain = "localhost"; + SOGoSelectedAddressBook = "collected"; SOGoMailMessageCheck = "manually"; SOGoMailMessageForwarding = "inline"; SOGoMailReplyPlacement = "below"; diff --git a/SoObjects/SOGo/SOGoParentFolder.h b/SoObjects/SOGo/SOGoParentFolder.h index 0413faafd..323e71d61 100644 --- a/SoObjects/SOGo/SOGoParentFolder.h +++ b/SoObjects/SOGo/SOGoParentFolder.h @@ -22,6 +22,7 @@ #define SOGOPARENTFOLDERS_H #import "SOGoFolder.h" +#import "SOGoConstants.h" @class NSMutableDictionary; @class NSString; @@ -39,6 +40,7 @@ + (Class) subFolderClass; - (NSString *) defaultFolderName; +- (NSString *) collectedFolderName; - (NSException *) appendPersonalSources; - (void) removeSubFolder: (NSString *) subfolderName; diff --git a/SoObjects/SOGo/SOGoParentFolder.m b/SoObjects/SOGo/SOGoParentFolder.m index da5a1c5b5..4c7c7c31a 100644 --- a/SoObjects/SOGo/SOGoParentFolder.m +++ b/SoObjects/SOGo/SOGoParentFolder.m @@ -38,7 +38,7 @@ #import #import #import - +#import #import #import "NSObject+DAV.h" @@ -153,9 +153,15 @@ static SoSecurityManager *sm = nil; return @"Personal"; } -- (void) _createPersonalFolder +- (NSString *) collectedFolderName +{ + return @"Collected"; +} + +- (void) createSpecialFolder: (SOGoFolderType) folderType { NSArray *roles; + NSString *folderName; SOGoGCSFolder *folder; SOGoUser *folderOwner; @@ -165,50 +171,70 @@ static SoSecurityManager *sm = nil; // We autocreate the calendars if the user is the owner, a superuser or // if it's a resource as we won't necessarily want to login as a resource // in order to create its database tables. + // FolderType is an enum where 0 = Personal and 1 = collected if ([roles containsObject: SoRole_Owner] || (folderOwner && [folderOwner isResource])) { - folder = [subFolderClass objectWithName: @"personal" inContainer: self]; - [folder setDisplayName: [self defaultFolderName]]; - [folder - setOCSPath: [NSString stringWithFormat: @"%@/personal", OCSPath]]; + if (folderType == SOGoPersonalFolder) + { + folderName = @"personal"; + folder = [subFolderClass objectWithName: folderName inContainer: self]; + [folder setDisplayName: [self defaultFolderName]]; + } + else if (folderType == SOGoCollectedFolder) + { + folderName = @"collected"; + folder = [subFolderClass objectWithName: folderName inContainer: self]; + [folder setDisplayName: [self collectedFolderName]]; + } + [folder setOCSPath: [NSString stringWithFormat: @"%@/%@", OCSPath, folderName]]; + if ([folder create]) - [subFolders setObject: folder forKey: @"personal"]; + [subFolders setObject: folder forKey: folderName]; } } -- (NSException *) _fetchPersonalFolders: (NSString *) sql - withChannel: (EOAdaptorChannel *) fc +- (NSException *) fetchSpecialFolders: (NSString *) sql + withChannel: (EOAdaptorChannel *) fc + andFolderType: (SOGoFolderType) folderType { NSArray *attrs; NSDictionary *row; SOGoGCSFolder *folder; NSString *key; NSException *error; + SOGoUserDefaults *ud; + ud = [[context activeUser] userDefaults]; if (!subFolderClass) subFolderClass = [[self class] subFolderClass]; error = [fc evaluateExpressionX: sql]; if (!error) + { + attrs = [fc describeResults: NO]; + while ((row = [fc fetchAttributes: attrs withZone: NULL])) { - attrs = [fc describeResults: NO]; - while ((row = [fc fetchAttributes: attrs withZone: NULL])) - { - key = [row objectForKey: @"c_path4"]; - if ([key isKindOfClass: [NSString class]]) - { - folder = [subFolderClass objectWithName: key inContainer: self]; - [folder setOCSPath: [NSString stringWithFormat: @"%@/%@", - OCSPath, key]]; - [subFolders setObject: folder forKey: key]; - } - } - - if (![subFolders objectForKey: @"personal"]) - [self _createPersonalFolder]; + key = [row objectForKey: @"c_path4"]; + if ([key isKindOfClass: [NSString class]]) + { + folder = [subFolderClass objectWithName: key inContainer: self]; + [folder setOCSPath: [NSString stringWithFormat: @"%@/%@", OCSPath, key]]; + [subFolders setObject: folder forKey: key]; + } } - + if (folderType == SOGoPersonalFolder) + { + if (![subFolders objectForKey: @"personal"]) + [self createSpecialFolder: SOGoPersonalFolder]; + } + else if (folderType == SOGoCollectedFolder) + { + if (![subFolders objectForKey: @"collected"]) + if ([[ud selectedAddressBook] isEqualToString:@"collected"]) + [self createSpecialFolder: SOGoCollectedFolder]; + } + } return error; } @@ -221,25 +247,21 @@ static SoSecurityManager *sm = nil; NSException *error; cm = [GCSChannelManager defaultChannelManager]; - folderLocation - = [[GCSFolderManager defaultFolderManager] folderInfoLocation]; + folderLocation = [[GCSFolderManager defaultFolderManager] folderInfoLocation]; fc = [cm acquireOpenChannelForURL: folderLocation]; if ([fc isOpen]) - { - gcsFolderType = [[self class] gcsFolderType]; - - sql - = [NSString stringWithFormat: (@"SELECT c_path4 FROM %@" - @" WHERE c_path2 = '%@'" - @" AND c_folder_type = '%@'"), - [folderLocation gcsTableName], - owner, - gcsFolderType]; - error = [self _fetchPersonalFolders: sql withChannel: fc]; - [cm releaseChannel: fc]; -// sql = [sql stringByAppendingFormat:@" WHERE %@ = '%@'", -// uidColumnName, [self uid]]; - } + { + gcsFolderType = [[self class] gcsFolderType]; + + sql = [NSString stringWithFormat: (@"SELECT c_path4 FROM %@" + @" WHERE c_path2 = '%@'" + @" AND c_folder_type = '%@'"), + [folderLocation gcsTableName], owner, gcsFolderType]; + + error = [self fetchSpecialFolders: sql withChannel: fc andFolderType: SOGoPersonalFolder]; + + [cm releaseChannel: fc]; + } else error = [NSException exceptionWithName: @"SOGoDBException" reason: @"database connection could not be open" @@ -248,6 +270,7 @@ static SoSecurityManager *sm = nil; return error; } + - (NSException *) appendSystemSources { return nil; @@ -388,12 +411,15 @@ static SoSecurityManager *sm = nil; subFolders = [NSMutableDictionary new]; error = [self appendPersonalSources]; if (!error) - error = [self appendSystemSources]; + if ([self respondsToSelector:@selector(appendCollectedSources)]) + error = [self appendCollectedSources]; + if (!error) + error = [self appendSystemSources]; // TODO : Not really a testcase, see function if (error) - { - [subFolders release]; - subFolders = nil; - } + { + [subFolders release]; + subFolders = nil; + } } else error = nil; diff --git a/SoObjects/SOGo/SOGoUserDefaults.h b/SoObjects/SOGo/SOGoUserDefaults.h index 83d6c18bb..b8df5621b 100644 --- a/SoObjects/SOGo/SOGoUserDefaults.h +++ b/SoObjects/SOGo/SOGoUserDefaults.h @@ -87,6 +87,9 @@ extern NSString *SOGoWeekStartFirstFullWeek; - (NSString *) language; /* mail */ +- (void) setMailAddOutgoingAddresses: (BOOL) newValue; +- (BOOL) mailAddOutgoingAddresses; + - (void) setMailShowSubscribedFoldersOnly: (BOOL) newValue; - (BOOL) mailShowSubscribedFoldersOnly; @@ -111,6 +114,9 @@ extern NSString *SOGoWeekStartFirstFullWeek; - (void) setMailListViewColumnsOrder: (NSArray *) newValue; - (NSArray *) mailListViewColumnsOrder; +- (void) setSelectedAddressBook: (NSString *) newValue; +- (NSString *) selectedAddressBook; + - (void) setMailMessageCheck: (NSString *) newValue; - (NSString *) mailMessageCheck; diff --git a/SoObjects/SOGo/SOGoUserDefaults.m b/SoObjects/SOGo/SOGoUserDefaults.m index b862c5523..d6d1c3999 100644 --- a/SoObjects/SOGo/SOGoUserDefaults.m +++ b/SoObjects/SOGo/SOGoUserDefaults.m @@ -185,8 +185,8 @@ NSString *SOGoWeekStartFirstFullWeek = @"FirstFullWeek"; { migratedKeys = [NSDictionary dictionaryWithObjectsAndKeys: - @"SOGoLoginModule", @"SOGoUIxDefaultModule", - @"SOGoLoginModule", @"SOGoDefaultModule", + @"SOGoLoginModule", @"SOGoUIxDefaultModule", + @"SOGoLoginModule", @"SOGoDefaultModule", @"SOGoTimeFormat", @"TimeFormat", @"SOGoShortDateFormat", @"ShortDateFormat", @"SOGoLongDateFormat", @"LongDateFormat", @@ -197,6 +197,7 @@ NSString *SOGoWeekStartFirstFullWeek = @"FirstFullWeek"; @"SOGoLanguage", @"SOGoDefaultLanguage", @"SOGoLanguage", @"Language", @"SOGoMailComposeMessageType", @"ComposeMessagesType", + @"SOGoSelectedAddressBook", @"SelectedAddressBook", @"SOGoMailMessageCheck", @"MessageCheck", @"SOGoMailMessageForwarding", @"MessageForwarding", @"SOGoMailSignature", @"MailSignature", @@ -384,6 +385,16 @@ NSString *SOGoWeekStartFirstFullWeek = @"FirstFullWeek"; return userLanguage; } +- (void) setMailAddOutgoingAddresses: (BOOL) newValue +{ + [self setBool: newValue forKey: @"SOGoMailAddOutgoingAddresses"]; +} + +- (BOOL) mailAddOutgoingAddresses +{ + return [self boolForKey: @"SOGoMailAddOutgoingAddresses"]; +} + - (void) setMailShowSubscribedFoldersOnly: (BOOL) newValue { [self setBool: newValue forKey: @"SOGoMailShowSubscribedFoldersOnly"]; @@ -467,6 +478,16 @@ NSString *SOGoWeekStartFirstFullWeek = @"FirstFullWeek"; return [self stringArrayForKey: @"SOGoMailListViewColumnsOrder"]; } +- (void) setSelectedAddressBook:(NSString *) newValue +{ + [self setObject: newValue forKey: @"SOGoSelectedAddressBook"]; +} + +- (NSString *) selectedAddressBook +{ + return [self stringForKey: @"SOGoSelectedAddressBook"]; +} + - (void) setMailMessageCheck: (NSString *) newValue { [self setObject: newValue forKey: @"SOGoMailMessageCheck"]; diff --git a/UI/Contacts/UIxContactFoldersView.m b/UI/Contacts/UIxContactFoldersView.m index f38a3532f..aaf35d6c2 100644 --- a/UI/Contacts/UIxContactFoldersView.m +++ b/UI/Contacts/UIxContactFoldersView.m @@ -158,88 +158,23 @@ Class SOGoContactSourceFolderK, SOGoGCSFolderK; - (id ) allContactSearchAction { id result; - SOGoFolder *folder; - NSString *searchText, *mail, *domain; + NSString *searchText; NSDictionary *data; - NSArray *folders, *contacts, *descriptors, *sortedContacts; - NSMutableArray *sortedFolders; - NSMutableDictionary *contact, *uniqueContacts; - unsigned int i, j, max; - NSSortDescriptor *commonNameDescriptor; + NSArray *sortedContacts; + BOOL excludeGroups, excludeLists; searchText = [self queryParameterForKey: @"search"]; if ([searchText length] > 0) { - // NSLog(@"Search all contacts: %@", searchText); excludeGroups = [[self queryParameterForKey: @"excludeGroups"] boolValue]; excludeLists = [[self queryParameterForKey: @"excludeLists"] boolValue]; - domain = [[context activeUser] domain]; - folders = nil; - NS_DURING - folders = [[self clientObject] subFolders]; - NS_HANDLER - /* We need to specifically test for @"SOGoDBException", which is - raised explicitly in SOGoParentFolder. Any other exception should - be re-raised. */ - if ([[localException name] isEqualToString: @"SOGoDBException"]) - folders = nil; - else - [localException raise]; - NS_ENDHANDLER; - max = [folders count]; - sortedFolders = [NSMutableArray arrayWithCapacity: max]; - uniqueContacts = [NSMutableDictionary dictionary]; - for (i = 0; i < max; i++) - { - folder = [folders objectAtIndex: i]; - /* We first search in LDAP folders (in case of duplicated entries in GCS folders) */ - if ([folder isKindOfClass: SOGoContactSourceFolderK]) - [sortedFolders insertObject: folder atIndex: 0]; - else - [sortedFolders addObject: folder]; - } - for (i = 0; i < max; i++) - { - folder = [sortedFolders objectAtIndex: i]; - //NSLog(@" Address book: %@ (%@)", [folder displayName], [folder class]); - contacts = [folder lookupContactsWithFilter: searchText - onCriteria: @"name_or_address" - sortBy: @"c_cn" - ordering: NSOrderedAscending - inDomain: domain]; - for (j = 0; j < [contacts count]; j++) - { - contact = [contacts objectAtIndex: j]; - mail = [contact objectForKey: @"c_mail"]; - //NSLog(@" found %@ (%@) ? %@", [contact objectForKey: @"c_name"], mail, - // [contact description]); - if (!excludeLists && [[contact objectForKey: @"c_component"] - isEqualToString: @"vlist"]) - { - [contact setObject: [folder nameInContainer] - forKey: @"container"]; - [uniqueContacts setObject: contact - forKey: [contact objectForKey: @"c_name"]]; - } - else if ([mail length] - && [uniqueContacts objectForKey: mail] == nil - && !(excludeGroups && [contact objectForKey: @"isGroup"])) - [uniqueContacts setObject: contact forKey: mail]; - } - } - if ([uniqueContacts count] > 0) - { - // Sort the contacts by display name - commonNameDescriptor = [[NSSortDescriptor alloc] initWithKey: @"c_cn" - ascending:YES]; - descriptors = [NSArray arrayWithObjects: commonNameDescriptor, nil]; - [commonNameDescriptor release]; - sortedContacts = [[uniqueContacts allValues] - sortedArrayUsingDescriptors: descriptors]; - } - else - sortedContacts = [NSArray array]; + + sortedContacts = [[self clientObject] allContactsFromFilter: searchText + excludeGroups: excludeGroups + excludeLists: excludeLists]; + + data = [NSDictionary dictionaryWithObjectsAndKeys: searchText, @"searchText", sortedContacts, @"contacts", nil]; diff --git a/UI/PreferencesUI/English.lproj/Localizable.strings b/UI/PreferencesUI/English.lproj/Localizable.strings index 8337f3e1e..ccd8890a4 100644 --- a/UI/PreferencesUI/English.lproj/Localizable.strings +++ b/UI/PreferencesUI/English.lproj/Localizable.strings @@ -97,8 +97,7 @@ "Show time as busy outside working hours" = "Show time as busy outside working hours"; "First week of year :" = "First week of year:"; "Enable reminders for Calendar items" = "Enable reminders for Calendar items"; -"Play a sound when a reminder comes due" -= "Play a sound when a reminder comes due"; +"Play a sound when a reminder comes due" = "Play a sound when a reminder comes due"; "Default reminder :" = "Default reminder:"; "firstWeekOfYear_January1" = "Starts on january 1"; @@ -157,6 +156,10 @@ "displayremoteinlineimages_never" = "Never"; "displayremoteinlineimages_always" = "Always"; +/* Contact */ +"Personal Address Book" = "Personal Address Book"; +"Collected Address Book" = "Collected Address Book"; + /* IMAP Accounts */ "New Mail Account" = "New Mail Account"; diff --git a/UI/PreferencesUI/French.lproj/Localizable.strings b/UI/PreferencesUI/French.lproj/Localizable.strings index 2470d9e10..bddf46ede 100644 --- a/UI/PreferencesUI/French.lproj/Localizable.strings +++ b/UI/PreferencesUI/French.lproj/Localizable.strings @@ -157,6 +157,10 @@ "displayremoteinlineimages_never" = "Jamais"; "displayremoteinlineimages_always" = "Toujours"; +/* Contact */ +"Personal Address Book" = "Carnet d'adresses personnel"; +"Collected Address Book" = "Carnet d'adresses collectés"; + /* IMAP Accounts */ "New Mail Account" = "Nouveau compte"; diff --git a/UI/PreferencesUI/UIxPreferences.h b/UI/PreferencesUI/UIxPreferences.h index 3040e67ae..9c8a3483f 100644 --- a/UI/PreferencesUI/UIxPreferences.h +++ b/UI/PreferencesUI/UIxPreferences.h @@ -33,6 +33,9 @@ id item; SOGoUser *user; + // Addressbook + NSMutableDictionary *addressBooksIDWithDisplayName; + // Calendar categories NSString *category; NSArray *calendarCategories; diff --git a/UI/PreferencesUI/UIxPreferences.m b/UI/PreferencesUI/UIxPreferences.m index b888ab906..0c59ffa02 100644 --- a/UI/PreferencesUI/UIxPreferences.m +++ b/UI/PreferencesUI/UIxPreferences.m @@ -51,6 +51,8 @@ #import #import +#import + #import "UIxPreferences.h" #warning this class is not finished @@ -115,6 +117,7 @@ static NSArray *reminderValues = nil; if ((self = [super init])) { item = nil; + addressBooksIDWithDisplayName = nil; #warning user should be the owner rather than the activeUser ASSIGN (user, [context activeUser]); ASSIGN (today, [NSCalendarDate date]); @@ -175,6 +178,7 @@ static NSArray *reminderValues = nil; [contactsCategories release]; [forwardOptions release]; [daysOfWeek release]; + [addressBooksIDWithDisplayName release]; [super dealloc]; } @@ -657,6 +661,16 @@ static NSArray *reminderValues = nil; } /* Mailer */ +- (void) setAddOutgoingAddresses: (BOOL) addOutgoingAddresses +{ + [userDefaults setMailAddOutgoingAddresses: addOutgoingAddresses]; +} + +- (BOOL) addOutgoingAddresses +{ + return [userDefaults mailAddOutgoingAddresses]; +} + - (void) setShowSubscribedFoldersOnly: (BOOL) showSubscribedFoldersOnly { [userDefaults setMailShowSubscribedFoldersOnly: showSubscribedFoldersOnly]; @@ -677,6 +691,67 @@ static NSArray *reminderValues = nil; return [userDefaults mailSortByThreads]; } +- (NSArray *) addressBookList +{ + /* We want all the SourceIDS */ + NSMutableArray *folders, *contactFolders, *availableAddressBooksID, *availableAddressBooksName; + int i, count; + BOOL collectedAlreadyExist; + + contactFolders = [[[context activeUser] homeFolderInContext: context] + lookupName: @"Contacts" + inContext: context + acquire: NO]; + folders = [NSMutableArray arrayWithArray: [contactFolders subFolders]]; + count = [folders count]-1; + + // Inside this loop we remove all the public or shared addressbooks + for (count; count >= 0; count--) + { + if (![[folders objectAtIndex: count] isKindOfClass: [SOGoContactGCSFolder class]]) + [folders removeObjectAtIndex: count]; + } + + // Parse the objects in order to have only the displayName of the addressbooks to be displayed on the preferences interface + availableAddressBooksID = [NSMutableArray arrayWithCapacity: [folders count]]; + availableAddressBooksName = [NSMutableArray arrayWithCapacity: [folders count]]; + count = [folders count]-1; + collectedAlreadyExist = false; + + for (i = 0; i <= count ; i++) { + [availableAddressBooksID addObject:[[folders objectAtIndex:i] realNameInContainer]]; + [availableAddressBooksName addObject:[[folders objectAtIndex:i] displayName]]; + + if ([[availableAddressBooksID objectAtIndex:i] isEqualToString: @"collected"]) + collectedAlreadyExist = true; + } + // Create the dictionary for the next function : itemAddressBookText. + if (!addressBooksIDWithDisplayName) + addressBooksIDWithDisplayName = [[NSMutableDictionary alloc] initWithObjects:availableAddressBooksName + forKeys:availableAddressBooksID]; + if (!collectedAlreadyExist) + { + [availableAddressBooksID addObject: @"collected"]; + [addressBooksIDWithDisplayName setObject: [self labelForKey: @"Collected Address Book"] forKey: @"collected"]; + } + + return availableAddressBooksID; +} +- (NSString *) itemAddressBookText +{ + return [addressBooksIDWithDisplayName objectForKey: item]; +} + +- (NSString *) userAddressBook +{ + return [userDefaults selectedAddressBook]; +} + +- (void) setUserAddressBook: (NSString *) newSelectedAddressBook +{ + [userDefaults setSelectedAddressBook: newSelectedAddressBook]; +} + - (NSArray *) messageCheckList { NSArray *intervalsList; diff --git a/UI/Templates/PreferencesUI/UIxPreferences.wox b/UI/Templates/PreferencesUI/UIxPreferences.wox index f626accb2..ebed82bbd 100644 --- a/UI/Templates/PreferencesUI/UIxPreferences.wox +++ b/UI/Templates/PreferencesUI/UIxPreferences.wox @@ -296,6 +296,16 @@ const:id="sortByThreads" var:checked="sortByThreads" /> +
+ +
+