New feature : 1496; Unknown outgoing email addresses can now be automatically be added to your address books.
parent
31ace947cb
commit
76307cfaaf
|
@ -1 +1,2 @@
|
||||||
"Personal Address Book" = "Personal Address Book";
|
"Personal Address Book" = "Personal Address Book";
|
||||||
|
"Collected Address Book" = "Collected Address Book";
|
||||||
|
|
|
@ -25,12 +25,20 @@
|
||||||
|
|
||||||
@interface SOGoContactFolders : SOGoParentFolder
|
@interface SOGoContactFolders : SOGoParentFolder
|
||||||
|
|
||||||
|
- (NSString *) defaultFolderName;
|
||||||
|
- (NSString *) collectedFolderName;
|
||||||
|
|
||||||
|
- (NSException *) appendCollectedSources;
|
||||||
- (NSException *) renameLDAPAddressBook: (NSString *) sourceID
|
- (NSException *) renameLDAPAddressBook: (NSString *) sourceID
|
||||||
withDisplayName: (NSString *) newDisplayName;
|
withDisplayName: (NSString *) newDisplayName;
|
||||||
- (NSException *) removeLDAPAddressBook: (NSString *) sourceID;
|
- (NSException *) removeLDAPAddressBook: (NSString *) sourceID;
|
||||||
|
|
||||||
- (NSDictionary *) systemSources;
|
- (NSDictionary *) systemSources;
|
||||||
|
|
||||||
|
- (NSArray *) allContactsFromFilter: (NSString *) theFilter
|
||||||
|
excludeGroups: (BOOL) excludeGroups
|
||||||
|
excludeLists: (BOOL) excludeLists;
|
||||||
|
|
||||||
@end
|
@end
|
||||||
|
|
||||||
#endif /* SOGOCONTACTFOLDERS_H */
|
#endif /* SOGOCONTACTFOLDERS_H */
|
||||||
|
|
|
@ -22,12 +22,18 @@
|
||||||
#import <Foundation/NSDictionary.h>
|
#import <Foundation/NSDictionary.h>
|
||||||
#import <Foundation/NSString.h>
|
#import <Foundation/NSString.h>
|
||||||
#import <Foundation/NSEnumerator.h>
|
#import <Foundation/NSEnumerator.h>
|
||||||
|
#import <Foundation/NSSortDescriptor.h>
|
||||||
|
|
||||||
#import <NGObjWeb/WOContext+SoObjects.h>
|
#import <NGObjWeb/WOContext+SoObjects.h>
|
||||||
#import <NGObjWeb/NSException+HTTP.h>
|
#import <NGObjWeb/NSException+HTTP.h>
|
||||||
#import <DOM/DOMElement.h>
|
#import <DOM/DOMElement.h>
|
||||||
#import <DOM/DOMProtocols.h>
|
#import <DOM/DOMProtocols.h>
|
||||||
|
|
||||||
|
#import <GDLContentStore/GCSChannelManager.h>
|
||||||
|
#import <GDLContentStore/GCSFolderManager.h>
|
||||||
|
#import <GDLContentStore/NSURL+GCS.h>
|
||||||
|
#import <GDLAccess/EOAdaptorChannel.h>
|
||||||
|
|
||||||
#import <SOGo/NSObject+DAV.h>
|
#import <SOGo/NSObject+DAV.h>
|
||||||
#import <SOGo/SOGoUser.h>
|
#import <SOGo/SOGoUser.h>
|
||||||
#import <SOGo/SOGoUserDefaults.h>
|
#import <SOGo/SOGoUserDefaults.h>
|
||||||
|
@ -40,10 +46,17 @@
|
||||||
|
|
||||||
#import "SOGoContactFolders.h"
|
#import "SOGoContactFolders.h"
|
||||||
|
|
||||||
|
Class SOGoContactSourceFolderK;
|
||||||
|
|
||||||
#define XMLNS_INVERSEDAV @"urn:inverse:params:xml:ns:inverse-dav"
|
#define XMLNS_INVERSEDAV @"urn:inverse:params:xml:ns:inverse-dav"
|
||||||
|
|
||||||
@implementation SOGoContactFolders
|
@implementation SOGoContactFolders
|
||||||
|
|
||||||
|
+ (void) initialize
|
||||||
|
{
|
||||||
|
SOGoContactSourceFolderK = [SOGoContactSourceFolder class];
|
||||||
|
}
|
||||||
|
|
||||||
+ (NSString *) gcsFolderType
|
+ (NSString *) gcsFolderType
|
||||||
{
|
{
|
||||||
return @"Contact";
|
return @"Contact";
|
||||||
|
@ -110,6 +123,92 @@
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
- (void) _createCollectedFolder
|
||||||
|
{
|
||||||
|
NSArray *roles;
|
||||||
|
SOGoGCSFolder *folder;
|
||||||
|
SOGoUser *folderOwner;
|
||||||
|
|
||||||
|
roles = [[context activeUser] rolesForObject: self inContext: context];
|
||||||
|
folderOwner = [SOGoUser userWithLogin: [self ownerInContext: context]];
|
||||||
|
|
||||||
|
if (folderOwner && [folderOwner isResource])
|
||||||
|
{
|
||||||
|
folder = [subFolderClass objectWithName: @"collected" inContainer: self];
|
||||||
|
[folder setDisplayName: [self collectedFolderName]];
|
||||||
|
[folder setOCSPath: [NSString stringWithFormat: @"%@/collected", OCSPath]];
|
||||||
|
if ([folder create])
|
||||||
|
[subFolders setObject: folder forKey: @"collected"];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
- (NSException *) _fetchCollectedFolders: (NSString *) sql
|
||||||
|
withChannel: (EOAdaptorChannel *) fc
|
||||||
|
{
|
||||||
|
NSArray *attrs;
|
||||||
|
NSDictionary *row;
|
||||||
|
SOGoGCSFolder *folder;
|
||||||
|
NSString *key;
|
||||||
|
NSException *error;
|
||||||
|
|
||||||
|
if (!subFolderClass)
|
||||||
|
subFolderClass = [[self class] subFolderClass];
|
||||||
|
|
||||||
|
error = [fc evaluateExpressionX: sql];
|
||||||
|
if (!error)
|
||||||
|
{
|
||||||
|
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: @"collected"])
|
||||||
|
[self _createCollectedFolder];
|
||||||
|
}
|
||||||
|
|
||||||
|
return error;
|
||||||
|
}
|
||||||
|
|
||||||
|
- (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 = [self _fetchCollectedFolders: sql withChannel: fc];
|
||||||
|
[cm releaseChannel: fc];
|
||||||
|
}
|
||||||
|
else
|
||||||
|
error = [NSException exceptionWithName: @"SOGoDBException"
|
||||||
|
reason: @"database connection could not be open"
|
||||||
|
userInfo: nil];
|
||||||
|
|
||||||
|
return error;
|
||||||
|
}
|
||||||
|
|
||||||
- (NSDictionary *) systemSources
|
- (NSDictionary *) systemSources
|
||||||
{
|
{
|
||||||
NSMutableDictionary *systemSources;
|
NSMutableDictionary *systemSources;
|
||||||
|
@ -223,9 +322,9 @@
|
||||||
SOGoUser *currentUser;
|
SOGoUser *currentUser;
|
||||||
id <SOGoSource> source;
|
id <SOGoSource> source;
|
||||||
|
|
||||||
if ([sourceID isEqualToString: @"personal"])
|
if ([sourceID isEqualToString: @"personal"] || [sourceID isEqualToString: @"collected"])
|
||||||
result = [NSException exceptionWithHTTPStatus: 403
|
result = [NSException exceptionWithHTTPStatus: 403
|
||||||
reason: @"folder 'personal' cannot be deleted"];
|
reason: (@"folder '%@' cannot be deleted", sourceID)];
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
result = nil;
|
result = nil;
|
||||||
|
@ -250,6 +349,11 @@
|
||||||
return [self labelForKey: @"Personal Address Book"];
|
return [self labelForKey: @"Personal Address Book"];
|
||||||
}
|
}
|
||||||
|
|
||||||
|
- (NSString *) collectedFolderName
|
||||||
|
{
|
||||||
|
return [self labelForKey: @"Collected Address Book"];
|
||||||
|
}
|
||||||
|
|
||||||
- (NSArray *) toManyRelationshipKeys
|
- (NSArray *) toManyRelationshipKeys
|
||||||
{
|
{
|
||||||
NSMutableArray *keys;
|
NSMutableArray *keys;
|
||||||
|
@ -371,4 +475,89 @@
|
||||||
asWebDAVValue];
|
asWebDAVValue];
|
||||||
}
|
}
|
||||||
|
|
||||||
|
- (NSArray *) allContactsFromFilter: (NSString *) theFilter
|
||||||
|
excludeGroups: (BOOL) excludeGroups
|
||||||
|
excludeLists: (BOOL) excludeLists
|
||||||
|
{
|
||||||
|
SOGoFolder <SOGoContactFolder> *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
|
@end
|
||||||
|
|
|
@ -102,6 +102,8 @@
|
||||||
- (NSData *) mimeMessageAsData;
|
- (NSData *) mimeMessageAsData;
|
||||||
|
|
||||||
/* operations */
|
/* operations */
|
||||||
|
- (NSArray *) allRecipients;
|
||||||
|
- (NSArray *) allBareRecipients;
|
||||||
|
|
||||||
- (NSException *) delete;
|
- (NSException *) delete;
|
||||||
- (NSException *) sendMail;
|
- (NSException *) sendMail;
|
||||||
|
|
|
@ -45,6 +45,7 @@
|
||||||
#import <NGImap4/NGImap4Client.h>
|
#import <NGImap4/NGImap4Client.h>
|
||||||
#import <NGImap4/NGImap4Envelope.h>
|
#import <NGImap4/NGImap4Envelope.h>
|
||||||
#import <NGImap4/NGImap4EnvelopeAddress.h>
|
#import <NGImap4/NGImap4EnvelopeAddress.h>
|
||||||
|
#import <NGMail/NGMailAddressParser.h>
|
||||||
#import <NGMail/NGMimeMessage.h>
|
#import <NGMail/NGMimeMessage.h>
|
||||||
#import <NGMail/NGMimeMessageGenerator.h>
|
#import <NGMail/NGMimeMessageGenerator.h>
|
||||||
#import <NGMime/NGMimeBodyPart.h>
|
#import <NGMime/NGMimeBodyPart.h>
|
||||||
|
@ -63,6 +64,11 @@
|
||||||
#import <SOGo/SOGoUser.h>
|
#import <SOGo/SOGoUser.h>
|
||||||
#import <SOGo/SOGoUserDefaults.h>
|
#import <SOGo/SOGoUserDefaults.h>
|
||||||
|
|
||||||
|
#import <NGCards/NGVCard.h>
|
||||||
|
|
||||||
|
#import <Contacts/SOGoContactFolders.h>
|
||||||
|
#import <Contacts/SOGoContactGCSEntry.h>
|
||||||
|
|
||||||
#import "NSData+Mail.h"
|
#import "NSData+Mail.h"
|
||||||
#import "NSString+Mail.h"
|
#import "NSString+Mail.h"
|
||||||
#import "SOGoMailAccount.h"
|
#import "SOGoMailAccount.h"
|
||||||
|
@ -1660,7 +1666,7 @@ static NSString *userAgent = nil;
|
||||||
{
|
{
|
||||||
recipients = [headers objectForKey: fieldNames[count]];
|
recipients = [headers objectForKey: fieldNames[count]];
|
||||||
if ([recipients count] > 0)
|
if ([recipients count] > 0)
|
||||||
[allRecipients addObjectsFromArray: recipients];
|
[allRecipients addObjectsFromArray: recipients];
|
||||||
}
|
}
|
||||||
|
|
||||||
return allRecipients;
|
return allRecipients;
|
||||||
|
@ -1689,6 +1695,71 @@ static NSString *userAgent = nil;
|
||||||
//
|
//
|
||||||
- (NSException *) sendMail
|
- (NSException *) sendMail
|
||||||
{
|
{
|
||||||
|
SOGoUserDefaults *ud;
|
||||||
|
ud = [[context activeUser] userDefaults];
|
||||||
|
|
||||||
|
if ([ud mailAddOutgoingAddresses]) {
|
||||||
|
NSMutableArray *recipients;
|
||||||
|
SOGoMailAccounts *folder;
|
||||||
|
NGMailAddressParser *parser;
|
||||||
|
SOGoContactFolders *contactFolders;
|
||||||
|
NSArray *contacts;
|
||||||
|
NSString *address, *mail, *name;
|
||||||
|
int i;
|
||||||
|
id parsedAddress;
|
||||||
|
|
||||||
|
contactFolders = [[[context activeUser] homeFolderInContext: context]
|
||||||
|
lookupName: @"Contacts"
|
||||||
|
inContext: context
|
||||||
|
acquire: NO];
|
||||||
|
|
||||||
|
recipients = [self allRecipients];
|
||||||
|
|
||||||
|
for (i = 0; i < [recipients count]; i++)
|
||||||
|
{
|
||||||
|
// The address contains a string. ex: "John Doe <sogo1@exemple.com>"
|
||||||
|
address = [recipients objectAtIndex: i];
|
||||||
|
|
||||||
|
parser = [NGMailAddressParser mailAddressParserWithString: address];
|
||||||
|
parsedAddress = [parser parse];
|
||||||
|
|
||||||
|
mail = [parsedAddress address];
|
||||||
|
name = [parsedAddress displayName];
|
||||||
|
|
||||||
|
contacts = [contactFolders allContactsFromFilter: mail
|
||||||
|
excludeGroups: YES
|
||||||
|
excludeLists: YES];
|
||||||
|
|
||||||
|
// If we don't get any results from the autocompletion code, we add it..
|
||||||
|
if ([contacts count] == 0)
|
||||||
|
{
|
||||||
|
SOGoContactFolder *folder;
|
||||||
|
Class c;
|
||||||
|
SOGoContactGCSEntry *contact;
|
||||||
|
NSString *uid;
|
||||||
|
NGVCard *card;
|
||||||
|
|
||||||
|
/* Here I want the selected address book on the preferences. */
|
||||||
|
NSString *addressBook;
|
||||||
|
addressBook = [ud selectedAddressBook];
|
||||||
|
|
||||||
|
folder = [contactFolders lookupName: addressBook inContext: context acquire: NO];
|
||||||
|
uid = [folder globallyUniqueObjectId];
|
||||||
|
|
||||||
|
card = [NGVCard cardWithUid: uid];
|
||||||
|
[card addEmail: mail types: nil];
|
||||||
|
|
||||||
|
c = NSClassFromString(@"SOGoContactGCSEntry");
|
||||||
|
contact = [c objectWithName: uid
|
||||||
|
inContainer: folder];
|
||||||
|
[contact setIsNew: YES];
|
||||||
|
|
||||||
|
[contact saveContentString: [card versitString]];
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
return [self sendMailAndCopyToSent: YES];
|
return [self sendMailAndCopyToSent: YES];
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -52,6 +52,7 @@
|
||||||
|
|
||||||
SOGoIMAPServer = "localhost";
|
SOGoIMAPServer = "localhost";
|
||||||
SOGoMailDomain = "localhost";
|
SOGoMailDomain = "localhost";
|
||||||
|
SOGoSelectedAddressBook = "collected";
|
||||||
SOGoMailMessageCheck = "manually";
|
SOGoMailMessageCheck = "manually";
|
||||||
SOGoMailMessageForwarding = "inline";
|
SOGoMailMessageForwarding = "inline";
|
||||||
SOGoMailReplyPlacement = "below";
|
SOGoMailReplyPlacement = "below";
|
||||||
|
|
|
@ -221,20 +221,17 @@ static SoSecurityManager *sm = nil;
|
||||||
NSException *error;
|
NSException *error;
|
||||||
|
|
||||||
cm = [GCSChannelManager defaultChannelManager];
|
cm = [GCSChannelManager defaultChannelManager];
|
||||||
folderLocation
|
folderLocation = [[GCSFolderManager defaultFolderManager] folderInfoLocation];
|
||||||
= [[GCSFolderManager defaultFolderManager] folderInfoLocation];
|
|
||||||
fc = [cm acquireOpenChannelForURL: folderLocation];
|
fc = [cm acquireOpenChannelForURL: folderLocation];
|
||||||
if ([fc isOpen])
|
if ([fc isOpen])
|
||||||
{
|
{
|
||||||
gcsFolderType = [[self class] gcsFolderType];
|
gcsFolderType = [[self class] gcsFolderType];
|
||||||
|
|
||||||
sql
|
sql = [NSString stringWithFormat: (@"SELECT c_path4 FROM %@"
|
||||||
= [NSString stringWithFormat: (@"SELECT c_path4 FROM %@"
|
@" WHERE c_path2 = '%@'"
|
||||||
@" WHERE c_path2 = '%@'"
|
@" AND c_folder_type = '%@'"),
|
||||||
@" AND c_folder_type = '%@'"),
|
[folderLocation gcsTableName], owner, gcsFolderType];
|
||||||
[folderLocation gcsTableName],
|
|
||||||
owner,
|
|
||||||
gcsFolderType];
|
|
||||||
error = [self _fetchPersonalFolders: sql withChannel: fc];
|
error = [self _fetchPersonalFolders: sql withChannel: fc];
|
||||||
[cm releaseChannel: fc];
|
[cm releaseChannel: fc];
|
||||||
// sql = [sql stringByAppendingFormat:@" WHERE %@ = '%@'",
|
// sql = [sql stringByAppendingFormat:@" WHERE %@ = '%@'",
|
||||||
|
@ -248,6 +245,7 @@ static SoSecurityManager *sm = nil;
|
||||||
return error;
|
return error;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
- (NSException *) appendSystemSources
|
- (NSException *) appendSystemSources
|
||||||
{
|
{
|
||||||
return nil;
|
return nil;
|
||||||
|
@ -386,14 +384,17 @@ static SoSecurityManager *sm = nil;
|
||||||
if (!subFolders)
|
if (!subFolders)
|
||||||
{
|
{
|
||||||
subFolders = [NSMutableDictionary new];
|
subFolders = [NSMutableDictionary new];
|
||||||
error = [self appendPersonalSources];
|
error = [self appendPersonalSources];
|
||||||
if (!error)
|
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)
|
if (error)
|
||||||
{
|
{
|
||||||
[subFolders release];
|
[subFolders release];
|
||||||
subFolders = nil;
|
subFolders = nil;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
error = nil;
|
error = nil;
|
||||||
|
|
|
@ -87,6 +87,9 @@ extern NSString *SOGoWeekStartFirstFullWeek;
|
||||||
- (NSString *) language;
|
- (NSString *) language;
|
||||||
|
|
||||||
/* mail */
|
/* mail */
|
||||||
|
- (void) setMailAddOutgoingAddresses: (BOOL) newValue;
|
||||||
|
- (BOOL) mailAddOutgoingAddresses;
|
||||||
|
|
||||||
- (void) setMailShowSubscribedFoldersOnly: (BOOL) newValue;
|
- (void) setMailShowSubscribedFoldersOnly: (BOOL) newValue;
|
||||||
- (BOOL) mailShowSubscribedFoldersOnly;
|
- (BOOL) mailShowSubscribedFoldersOnly;
|
||||||
|
|
||||||
|
@ -111,6 +114,9 @@ extern NSString *SOGoWeekStartFirstFullWeek;
|
||||||
- (void) setMailListViewColumnsOrder: (NSArray *) newValue;
|
- (void) setMailListViewColumnsOrder: (NSArray *) newValue;
|
||||||
- (NSArray *) mailListViewColumnsOrder;
|
- (NSArray *) mailListViewColumnsOrder;
|
||||||
|
|
||||||
|
- (void) setSelectedAddressBook: (NSString *) newValue;
|
||||||
|
- (NSString *) selectedAddressBook;
|
||||||
|
|
||||||
- (void) setMailMessageCheck: (NSString *) newValue;
|
- (void) setMailMessageCheck: (NSString *) newValue;
|
||||||
- (NSString *) mailMessageCheck;
|
- (NSString *) mailMessageCheck;
|
||||||
|
|
||||||
|
|
|
@ -185,8 +185,8 @@ NSString *SOGoWeekStartFirstFullWeek = @"FirstFullWeek";
|
||||||
{
|
{
|
||||||
migratedKeys
|
migratedKeys
|
||||||
= [NSDictionary dictionaryWithObjectsAndKeys:
|
= [NSDictionary dictionaryWithObjectsAndKeys:
|
||||||
@"SOGoLoginModule", @"SOGoUIxDefaultModule",
|
@"SOGoLoginModule", @"SOGoUIxDefaultModule",
|
||||||
@"SOGoLoginModule", @"SOGoDefaultModule",
|
@"SOGoLoginModule", @"SOGoDefaultModule",
|
||||||
@"SOGoTimeFormat", @"TimeFormat",
|
@"SOGoTimeFormat", @"TimeFormat",
|
||||||
@"SOGoShortDateFormat", @"ShortDateFormat",
|
@"SOGoShortDateFormat", @"ShortDateFormat",
|
||||||
@"SOGoLongDateFormat", @"LongDateFormat",
|
@"SOGoLongDateFormat", @"LongDateFormat",
|
||||||
|
@ -197,6 +197,7 @@ NSString *SOGoWeekStartFirstFullWeek = @"FirstFullWeek";
|
||||||
@"SOGoLanguage", @"SOGoDefaultLanguage",
|
@"SOGoLanguage", @"SOGoDefaultLanguage",
|
||||||
@"SOGoLanguage", @"Language",
|
@"SOGoLanguage", @"Language",
|
||||||
@"SOGoMailComposeMessageType", @"ComposeMessagesType",
|
@"SOGoMailComposeMessageType", @"ComposeMessagesType",
|
||||||
|
@"SOGoSelectedAddressBook", @"SelectedAddressBook",
|
||||||
@"SOGoMailMessageCheck", @"MessageCheck",
|
@"SOGoMailMessageCheck", @"MessageCheck",
|
||||||
@"SOGoMailMessageForwarding", @"MessageForwarding",
|
@"SOGoMailMessageForwarding", @"MessageForwarding",
|
||||||
@"SOGoMailSignature", @"MailSignature",
|
@"SOGoMailSignature", @"MailSignature",
|
||||||
|
@ -384,6 +385,16 @@ NSString *SOGoWeekStartFirstFullWeek = @"FirstFullWeek";
|
||||||
return userLanguage;
|
return userLanguage;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
- (void) setMailAddOutgoingAddresses: (BOOL) newValue
|
||||||
|
{
|
||||||
|
[self setBool: newValue forKey: @"SOGoMailAddOutgoingAddresses"];
|
||||||
|
}
|
||||||
|
|
||||||
|
- (BOOL) mailAddOutgoingAddresses
|
||||||
|
{
|
||||||
|
return [self boolForKey: @"SOGoMailAddOutgoingAddresses"];
|
||||||
|
}
|
||||||
|
|
||||||
- (void) setMailShowSubscribedFoldersOnly: (BOOL) newValue
|
- (void) setMailShowSubscribedFoldersOnly: (BOOL) newValue
|
||||||
{
|
{
|
||||||
[self setBool: newValue forKey: @"SOGoMailShowSubscribedFoldersOnly"];
|
[self setBool: newValue forKey: @"SOGoMailShowSubscribedFoldersOnly"];
|
||||||
|
@ -467,6 +478,16 @@ NSString *SOGoWeekStartFirstFullWeek = @"FirstFullWeek";
|
||||||
return [self stringArrayForKey: @"SOGoMailListViewColumnsOrder"];
|
return [self stringArrayForKey: @"SOGoMailListViewColumnsOrder"];
|
||||||
}
|
}
|
||||||
|
|
||||||
|
- (void) setSelectedAddressBook:(NSString *) newValue
|
||||||
|
{
|
||||||
|
[self setObject: newValue forKey: @"SOGoSelectedAddressBook"];
|
||||||
|
}
|
||||||
|
|
||||||
|
- (NSString *) selectedAddressBook
|
||||||
|
{
|
||||||
|
return [self stringForKey: @"SOGoSelectedAddressBook"];
|
||||||
|
}
|
||||||
|
|
||||||
- (void) setMailMessageCheck: (NSString *) newValue
|
- (void) setMailMessageCheck: (NSString *) newValue
|
||||||
{
|
{
|
||||||
[self setObject: newValue forKey: @"SOGoMailMessageCheck"];
|
[self setObject: newValue forKey: @"SOGoMailMessageCheck"];
|
||||||
|
|
|
@ -158,88 +158,23 @@ Class SOGoContactSourceFolderK, SOGoGCSFolderK;
|
||||||
- (id <WOActionResults>) allContactSearchAction
|
- (id <WOActionResults>) allContactSearchAction
|
||||||
{
|
{
|
||||||
id <WOActionResults> result;
|
id <WOActionResults> result;
|
||||||
SOGoFolder <SOGoContactFolder> *folder;
|
NSString *searchText;
|
||||||
NSString *searchText, *mail, *domain;
|
|
||||||
NSDictionary *data;
|
NSDictionary *data;
|
||||||
NSArray *folders, *contacts, *descriptors, *sortedContacts;
|
NSArray *sortedContacts;
|
||||||
NSMutableArray *sortedFolders;
|
|
||||||
NSMutableDictionary *contact, *uniqueContacts;
|
|
||||||
unsigned int i, j, max;
|
|
||||||
NSSortDescriptor *commonNameDescriptor;
|
|
||||||
BOOL excludeGroups, excludeLists;
|
BOOL excludeGroups, excludeLists;
|
||||||
|
|
||||||
searchText = [self queryParameterForKey: @"search"];
|
searchText = [self queryParameterForKey: @"search"];
|
||||||
if ([searchText length] > 0)
|
if ([searchText length] > 0)
|
||||||
{
|
{
|
||||||
// NSLog(@"Search all contacts: %@", searchText);
|
|
||||||
excludeGroups = [[self queryParameterForKey: @"excludeGroups"] boolValue];
|
excludeGroups = [[self queryParameterForKey: @"excludeGroups"] boolValue];
|
||||||
excludeLists = [[self queryParameterForKey: @"excludeLists"] boolValue];
|
excludeLists = [[self queryParameterForKey: @"excludeLists"] boolValue];
|
||||||
domain = [[context activeUser] domain];
|
|
||||||
folders = nil;
|
sortedContacts = [[self clientObject] allContactsFromFilter: searchText
|
||||||
NS_DURING
|
excludeGroups: excludeGroups
|
||||||
folders = [[self clientObject] subFolders];
|
excludeLists: excludeLists];
|
||||||
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];
|
|
||||||
data = [NSDictionary dictionaryWithObjectsAndKeys: searchText, @"searchText",
|
data = [NSDictionary dictionaryWithObjectsAndKeys: searchText, @"searchText",
|
||||||
sortedContacts, @"contacts",
|
sortedContacts, @"contacts",
|
||||||
nil];
|
nil];
|
||||||
|
|
|
@ -139,6 +139,8 @@
|
||||||
"messagecheck_every_20_minutes" = "Every 20 minutes";
|
"messagecheck_every_20_minutes" = "Every 20 minutes";
|
||||||
"messagecheck_every_30_minutes" = "Every 30 minutes";
|
"messagecheck_every_30_minutes" = "Every 30 minutes";
|
||||||
"messagecheck_once_per_hour" = "Once per hour";
|
"messagecheck_once_per_hour" = "Once per hour";
|
||||||
|
"PersonalAddressBook" = "Personal address book";
|
||||||
|
"CollectedAddressBook" = "Collected addresses";
|
||||||
|
|
||||||
"Forward messages:" = "Forward messages:";
|
"Forward messages:" = "Forward messages:";
|
||||||
"messageforward_inline" = "Inline";
|
"messageforward_inline" = "Inline";
|
||||||
|
|
|
@ -50,6 +50,8 @@
|
||||||
#import <Mailer/SOGoMailAccounts.h>
|
#import <Mailer/SOGoMailAccounts.h>
|
||||||
#import <Mailer/SOGoMailLabel.h>
|
#import <Mailer/SOGoMailLabel.h>
|
||||||
|
|
||||||
|
#import <Contacts/SOGoContactGCSFolder.h>
|
||||||
|
|
||||||
#import "UIxPreferences.h"
|
#import "UIxPreferences.h"
|
||||||
|
|
||||||
#warning this class is not finished
|
#warning this class is not finished
|
||||||
|
@ -656,6 +658,16 @@ static NSArray *reminderValues = nil;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Mailer */
|
/* Mailer */
|
||||||
|
- (void) setAddOutgoingAddresses: (BOOL) addOutgoingAddresses
|
||||||
|
{
|
||||||
|
[userDefaults setMailAddOutgoingAddresses: addOutgoingAddresses];
|
||||||
|
}
|
||||||
|
|
||||||
|
- (BOOL) addOutgoingAddresses
|
||||||
|
{
|
||||||
|
return [userDefaults mailAddOutgoingAddresses];
|
||||||
|
}
|
||||||
|
|
||||||
- (void) setShowSubscribedFoldersOnly: (BOOL) showSubscribedFoldersOnly
|
- (void) setShowSubscribedFoldersOnly: (BOOL) showSubscribedFoldersOnly
|
||||||
{
|
{
|
||||||
[userDefaults setMailShowSubscribedFoldersOnly: showSubscribedFoldersOnly];
|
[userDefaults setMailShowSubscribedFoldersOnly: showSubscribedFoldersOnly];
|
||||||
|
@ -676,6 +688,58 @@ static NSArray *reminderValues = nil;
|
||||||
return [userDefaults mailSortByThreads];
|
return [userDefaults mailSortByThreads];
|
||||||
}
|
}
|
||||||
|
|
||||||
|
- (NSArray *) addressBookList
|
||||||
|
{
|
||||||
|
/* We want all the SourceIDS */
|
||||||
|
NSMutableArray *folders;
|
||||||
|
NSMutableArray *contactFolders;
|
||||||
|
|
||||||
|
contactFolders = [[[context activeUser] homeFolderInContext: context]
|
||||||
|
lookupName: @"Contacts"
|
||||||
|
inContext: context
|
||||||
|
acquire: NO];
|
||||||
|
|
||||||
|
folders = [NSMutableArray arrayWithArray: [contactFolders subFolders]];
|
||||||
|
|
||||||
|
int i, count;
|
||||||
|
|
||||||
|
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
|
||||||
|
NSMutableArray *availableAddressBooks = [NSMutableArray new];
|
||||||
|
NSMutableArray *availableAddressBooksName = [NSMutableArray new];
|
||||||
|
|
||||||
|
count = [folders count]-1;
|
||||||
|
for (i=0; i <= count ; i++) {
|
||||||
|
[availableAddressBooks addObject:[[folders objectAtIndex:i] realNameInContainer]];
|
||||||
|
[availableAddressBooksName addObject:[[folders objectAtIndex:i] displayName]];
|
||||||
|
}
|
||||||
|
|
||||||
|
return availableAddressBooks;
|
||||||
|
|
||||||
|
}
|
||||||
|
- (NSString *) itemAddressBookText
|
||||||
|
{
|
||||||
|
return [self labelForKey:[NSString stringWithFormat: item]];
|
||||||
|
}
|
||||||
|
|
||||||
|
- (NSString *) userAddressBook
|
||||||
|
{
|
||||||
|
return [userDefaults selectedAddressBook];
|
||||||
|
}
|
||||||
|
|
||||||
|
- (void) setUserAddressBook: (NSString *) newSelectedAddressBook
|
||||||
|
{
|
||||||
|
[userDefaults setSelectedAddressBook: newSelectedAddressBook];
|
||||||
|
}
|
||||||
|
|
||||||
- (NSArray *) messageCheckList
|
- (NSArray *) messageCheckList
|
||||||
{
|
{
|
||||||
NSArray *intervalsList;
|
NSArray *intervalsList;
|
||||||
|
|
|
@ -294,6 +294,16 @@
|
||||||
const:id="sortByThreads"
|
const:id="sortByThreads"
|
||||||
var:checked="sortByThreads" />
|
var:checked="sortByThreads" />
|
||||||
<var:string label:value="Sort messages by threads"/></dd>
|
<var:string label:value="Sort messages by threads"/></dd>
|
||||||
|
<dd><input type="checkbox"
|
||||||
|
const:name="addOutgoingAddresses"
|
||||||
|
const:id="addOutgoingAddresses"
|
||||||
|
var:checked="addOutgoingAddresses" />
|
||||||
|
<var:string label:value="Automatically add outgoing e-mail addresses to my :"/>
|
||||||
|
<var:popup list="addressBookList" item="item"
|
||||||
|
const:id="addressBookList"
|
||||||
|
const:name="addressBookList"
|
||||||
|
string="itemAddressBookText" selection="userAddressBook"/></dd>
|
||||||
|
<dt></dt>
|
||||||
<dt><var:string label:value="Check for new mail:"/></dt>
|
<dt><var:string label:value="Check for new mail:"/></dt>
|
||||||
<dd><var:popup list="messageCheckList" item="item"
|
<dd><var:popup list="messageCheckList" item="item"
|
||||||
const:id="messageCheck"
|
const:id="messageCheck"
|
||||||
|
|
Loading…
Reference in New Issue