diff --git a/SoObjects/Contacts/NGVCard+SOGo.h b/SoObjects/Contacts/NGVCard+SOGo.h index 512037888..a52319ea9 100644 --- a/SoObjects/Contacts/NGVCard+SOGo.h +++ b/SoObjects/Contacts/NGVCard+SOGo.h @@ -34,6 +34,9 @@ - (void) updateFromLDIFRecord: (NSDictionary *) ldifRecord; - (NSMutableDictionary *) asLDIFRecord; +- (void) setAttributes: (NSDictionary *) attributes; +//- (NSDictionary *) attributes; + - (NSString *) workCompany; - (NSString *) fullName; - (NSArray *) secondaryEmails; diff --git a/SoObjects/Contacts/NGVCard+SOGo.m b/SoObjects/Contacts/NGVCard+SOGo.m index 83e646c06..f03c76064 100644 --- a/SoObjects/Contacts/NGVCard+SOGo.m +++ b/SoObjects/Contacts/NGVCard+SOGo.m @@ -642,6 +642,237 @@ convention: return ldifRecord; } +- (void) setAttributes: (NSDictionary *) attributes +{ + NSInteger year, yearOfToday, month, day; + CardElement *element; + NSCalendarDate *now; + NSArray *elements, *values; + NSMutableArray *addresses, *units, *categories; + NSString *ou; + id o; + unsigned int i; + + NSLog(@"setAttributes: %@", attributes); + + [self setNWithFamily: [attributes objectForKey: @"sn"] + given: [attributes objectForKey: @"givenname"] + additional: nil prefixes: nil suffixes: nil]; + [self setNickname: [attributes objectForKey: @"nickname"]]; + [self setFn: [attributes objectForKey: @"fn"]]; + [self setTitle: [attributes objectForKey: @"title"]]; + + // element = [self elementWithTag: @"adr" ofType: @"home"]; + // [element setSingleValue: [ldifRecord objectForKey: @"mozillahomestreet2"] + // atIndex: 1 forKey: @""]; + // [element setSingleValue: [ldifRecord objectForKey: @"mozillahomestreet"] + // atIndex: 2 forKey: @""]; + // [element setSingleValue: [ldifRecord objectForKey: @"mozillahomelocalityname"] + // atIndex: 3 forKey: @""]; + // [element setSingleValue: [ldifRecord objectForKey: @"mozillahomestate"] + // atIndex: 4 forKey: @""]; + // [element setSingleValue: [ldifRecord objectForKey: @"mozillahomepostalcode"] + // atIndex: 5 forKey: @""]; + // [element setSingleValue: [ldifRecord objectForKey: @"mozillahomecountryname"] + // atIndex: 6 forKey: @""]; + + // element = [self elementWithTag: @"adr" ofType: @"work"]; + // [element setSingleValue: [ldifRecord objectForKey: @"mozillaworkstreet2"] + // atIndex: 1 forKey: @""]; + // [element setSingleValue: [ldifRecord objectForKey: @"street"] + // atIndex: 2 forKey: @""]; + // [element setSingleValue: [ldifRecord objectForKey: @"l"] + // atIndex: 3 forKey: @""]; + // [element setSingleValue: [ldifRecord objectForKey: @"st"] + // atIndex: 4 forKey: @""]; + // [element setSingleValue: [ldifRecord objectForKey: @"postalcode"] + // atIndex: 5 forKey: @""]; + // [element setSingleValue: [ldifRecord objectForKey: @"c"] + // atIndex: 6 forKey: @""]; + if ([[attributes objectForKey: @"addresses"] isKindOfClass: [NSArray class]]) + { + elements = [self childrenWithTag: @"adr"]; + [self removeChildren: elements]; + values = [attributes objectForKey: @"addresses"]; + addresses = [NSMutableArray arrayWithCapacity: [values count]]; + for (i = 0; i < [values count]; i++) + { + o = [values objectAtIndex: i]; + if ([o isKindOfClass: [NSDictionary class]]) + { + element = [self elementWithTag: @"adr" ofType: [o objectForKey: @"type"]]; + [element setSingleValue: [o objectForKey: @"postoffice"] + atIndex: 0 forKey: @""]; + [element setSingleValue: [o objectForKey: @"street2"] + atIndex: 1 forKey: @""]; + [element setSingleValue: [o objectForKey: @"street"] + atIndex: 2 forKey: @""]; + [element setSingleValue: [o objectForKey: @"locality"] + atIndex: 3 forKey: @""]; + [element setSingleValue: [o objectForKey: @"region"] + atIndex: 4 forKey: @""]; + [element setSingleValue: [o objectForKey: @"postalcode"] + atIndex: 5 forKey: @""]; + [element setSingleValue: [o objectForKey: @"country"] + atIndex: 6 forKey: @""]; + } + } + } + + // ou = [ldifRecord objectForKey: @"ou"]; + // if (ou) + // units = [NSArray arrayWithObject: ou]; + // else + // units = nil; + // [self setOrg: [ldifRecord objectForKey: @"o"] + // units: units]; + if ([[attributes objectForKey: @"orgUnits"] isKindOfClass: [NSArray class]]) + { + elements = [self childrenWithTag: @"org"]; + [self removeChildren: elements]; + values = [attributes objectForKey: @"orgUnits"]; + units = [NSMutableArray arrayWithCapacity: [values count]]; + for (i = 0; i < [values count]; i++) + { + o = [values objectAtIndex: i]; + if ([o isKindOfClass: [NSDictionary class]]) + { + [units addObject: [o objectForKey: @"value"]]; + } + } + } + else + { + units = nil; + } + [self setOrg: [attributes objectForKey: @"org"] + units: units]; + + // [self _setPhoneValues: ldifRecord]; + + elements = [self childrenWithTag: @"tel"]; + [self removeChildren: elements]; + values = [attributes objectForKey: @"phones"]; + if ([values isKindOfClass: [NSArray class]]) + { + NSEnumerator *list = [values objectEnumerator]; + id attrs; + while ((attrs = [list nextObject])) + { + if ([attrs isKindOfClass: [NSDictionary class]]) + { + element = [self elementWithTag: @"tel" ofType: [attrs objectForKey: @"type"]]; + [element setSingleValue: [attrs objectForKey: @"value"] forKey: @""]; + } + } + } + + // [self _setEmails: ldifRecord]; + if ([[attributes objectForKey: @"emails"] isKindOfClass: [NSArray class]]) + { + elements = [self childrenWithTag: @"email"]; + [self removeChildren: elements]; + values = [attributes objectForKey: @"emails"]; + if (values) + { + NSEnumerator *list = [values objectEnumerator]; + //NSDictionary *attrs; + while ((o = [list nextObject])) + { + if ([o isKindOfClass: [NSDictionary class]]) + { + element = [self elementWithTag: @"email" ofType: [o objectForKey: @"type"]]; + [element setSingleValue: [o objectForKey: @"value"] forKey: @""]; + } + } + } + } + + // [[self elementWithTag: @"url" ofType: @"home"] + // setSingleValue: [ldifRecord objectForKey: @"mozillahomeurl"] forKey: @""]; + // [[self elementWithTag: @"url" ofType: @"work"] + // setSingleValue: [ldifRecord objectForKey: @"mozillaworkurl"] forKey: @""]; + + elements = [self childrenWithTag: @"url"]; + [self removeChildren: elements]; + values = [attributes objectForKey: @"urls"]; + if ([values isKindOfClass: [NSArray class]]) + { + NSEnumerator *list = [values objectEnumerator]; + id attrs; + while ((attrs = [list nextObject])) + { + if ([attrs isKindOfClass: [NSDictionary class]]) + { + element = [self elementWithTag: @"url" ofType: [attrs objectForKey: @"type"]]; + [element setSingleValue: [attrs objectForKey: @"value"] forKey: @""]; + } + } + } + + // [[self uniqueChildWithTag: @"x-aim"] + // setSingleValue: [ldifRecord objectForKey: @"nsaimid"] + // forKey: @""]; + + // now = [NSCalendarDate date]; + // year = [[ldifRecord objectForKey: @"birthyear"] intValue]; + // if (year < 100) + // { + // yearOfToday = [now yearOfCommonEra]; + // if (year == 0) + // year = yearOfToday; + // else if (yearOfToday < (year + 2000)) + // year += 1900; + // else + // year += 2000; + // } + // month = [[ldifRecord objectForKey: @"birthmonth"] intValue]; + // day = [[ldifRecord objectForKey: @"birthday"] intValue]; + + // if (year && month && day) + // [self setBday: [NSString stringWithFormat: @"%.4d-%.2d-%.2d", + // year, month, day]]; + // else + // [self setBday: @""]; + + // /* hack to carry SOGoLDAPContactInfo to vcards */ + // [[self uniqueChildWithTag: @"x-sogo-contactinfo"] + // setSingleValue: [ldifRecord objectForKey: @"c_info"] + // forKey: @""]; + + [self setNote: [attributes objectForKey: @"note"]]; + + // o = [ldifRecord objectForKey: @"vcardcategories"]; + + if ([[attributes objectForKey: @"categories"] isKindOfClass: [NSArray class]]) + { + elements = [self childrenWithTag: @"categories"]; + [self removeChildren: elements]; + values = [attributes objectForKey: @"categories"]; + categories = [NSMutableArray arrayWithCapacity: [values count]]; + for (i = 0; i < [values count]; i++) + { + o = [values objectAtIndex: i]; + if ([o isKindOfClass: [NSDictionary class]]) + { + [categories addObject: [o objectForKey: @"value"]]; + } + } + [self setCategories: categories]; + } + + // We can either have an array (from SOGo's web gui) or a + // string (from a LDIF import) as the value here. + // if ([o isKindOfClass: [NSArray class]]) + // [self setCategories: o]; + // else + // [self setCategories: [o componentsSeparatedByString: @","]]; + + [self cleanupEmptyChildren]; + + NSLog(@"%@", [self versitString]); +} + - (NSString *) workCompany { CardElement *org; diff --git a/SoObjects/Contacts/SOGoContactGCSEntry.m b/SoObjects/Contacts/SOGoContactGCSEntry.m index 4b5d5bd21..4af28fecd 100644 --- a/SoObjects/Contacts/SOGoContactGCSEntry.m +++ b/SoObjects/Contacts/SOGoContactGCSEntry.m @@ -84,6 +84,11 @@ return [self ldifRecord]; } +- (void) setAttributes: (NSDictionary *) newAttributes +{ + [[self vCard] setAttributes: newAttributes]; +} + - (BOOL) hasPhoto { return ([[self vCard] firstChildWithTag: @"photo"] != nil); diff --git a/SoObjects/Contacts/SOGoContactObject.h b/SoObjects/Contacts/SOGoContactObject.h index 3131a9f42..3f5b30c8c 100644 --- a/SoObjects/Contacts/SOGoContactObject.h +++ b/SoObjects/Contacts/SOGoContactObject.h @@ -37,6 +37,8 @@ - (NSDictionary *) ldifRecord; - (NSDictionary *) simplifiedLDIFRecord; +- (void) setAttributes: (NSDictionary *) newAttributes; + - (NSException *) save; - (NSException *) delete; diff --git a/UI/Contacts/UIxContactEditor.m b/UI/Contacts/UIxContactEditor.m index 418945337..81d170896 100644 --- a/UI/Contacts/UIxContactEditor.m +++ b/UI/Contacts/UIxContactEditor.m @@ -303,15 +303,15 @@ static Class SOGoContactGCSEntryK = Nil; /* actions */ -- (BOOL) shouldTakeValuesFromRequest: (WORequest *) request - inContext: (WOContext*) context -{ - NSString *actionName; - - actionName = [[request requestHandlerPath] lastPathComponent]; - - return ([actionName hasPrefix: @"save"]); -} +// - (BOOL) shouldTakeValuesFromRequest: (WORequest *) request +// inContext: (WOContext*) context +// { +// NSString *actionName; +// +// actionName = [[request requestHandlerPath] lastPathComponent]; +// +// return ([actionName hasPrefix: @"save"]); +// } - (NSString *) viewActionName { @@ -347,43 +347,80 @@ static Class SOGoContactGCSEntryK = Nil; - (id ) saveAction { SOGoObject *contact; - id result; - NSString *jsRefreshMethod; + WORequest *request; + WOResponse *response; + //id result; + NSDictionary *params; + //NSString *jsRefreshMethod; SoSecurityManager *sm; contact = [self clientObject]; - [contact setLDIFRecord: ldifRecord]; - [self _fetchAndCombineCategoriesList]; + request = [context request]; + NSLog(@"%@", [request contentAsString]); + params = [[request contentAsString] objectFromJSONString]; + + // LDIF NSDictionary (vCard) + // --------------------------------------------- + // sn familyname + // givenname givenname + // mozillanickname nickname + // displayname fullname + // title title + // o organization + // ou[] units[] + // telephonenumber tel;work + // homephone tel;home + // mobile tel;cell + // facsimiletelephonenumber tel;fax + // pager tel;pager + // mail email;work + // mozillasecondemail email;home + // mozillausehtmlmail x-mozilla-html + // mozillahomeurl url;home + // mozillaworkurl url;work + // nsaimid x-aim + // birth(year/month/day) bday + // c_info x-sogo-contactinfo + // description note + // vcardcategories categories + + [contact setAttributes: params]; + + response = [self responseWithStatus: 204]; + + //[contact setLDIFRecord: ldifRecord]; + //[self _fetchAndCombineCategoriesList]; [contact save]; - if (componentAddressBook && componentAddressBook != [self componentAddressBook]) - { - if ([contact isKindOfClass: SOGoContactGCSEntryK]) - { - sm = [SoSecurityManager sharedSecurityManager]; - if (![sm validatePermission: SoPerm_DeleteObjects - onObject: componentAddressBook - inContext: context] - && ![sm validatePermission: SoPerm_AddDocumentsImagesAndFiles - onObject: componentAddressBook - inContext: context]) - [(SOGoContactGCSEntry *) contact - moveToFolder: (SOGoGCSFolder *)componentAddressBook]; // TODO: - // handle - // exception - } - } +// if (componentAddressBook && componentAddressBook != [self componentAddressBook]) +// { +// if ([contact isKindOfClass: SOGoContactGCSEntryK]) +// { +// sm = [SoSecurityManager sharedSecurityManager]; +// if (![sm validatePermission: SoPerm_DeleteObjects +// onObject: componentAddressBook +// inContext: context] +// && ![sm validatePermission: SoPerm_AddDocumentsImagesAndFiles +// onObject: componentAddressBook +// inContext: context]) +// [(SOGoContactGCSEntry *) contact +// moveToFolder: (SOGoGCSFolder *)componentAddressBook]; // TODO: +// // handle +// // exception +// } +// } - if ([[[[self context] request] formValueForKey: @"nojs"] intValue]) - result = [self redirectToLocation: [self modulePath]]; - else - { - jsRefreshMethod = [NSString stringWithFormat: @"refreshContacts('%@')", - [contact nameInContainer]]; - result = [self jsCloseWithRefreshMethod: jsRefreshMethod]; - } + // if ([[[[self context] request] formValueForKey: @"nojs"] intValue]) + // result = [self redirectToLocation: [self modulePath]]; + // else + // { + // jsRefreshMethod + // = [NSString stringWithFormat: @"refreshContacts(\"%@\")", + // [contact nameInContainer]]; + // result = [self jsCloseWithRefreshMethod: jsRefreshMethod]; + // } - return result; + return response; } - (id) writeAction diff --git a/UI/Contacts/UIxContactFolderActions.m b/UI/Contacts/UIxContactFolderActions.m index 974e7d5d0..178db7579 100644 --- a/UI/Contacts/UIxContactFolderActions.m +++ b/UI/Contacts/UIxContactFolderActions.m @@ -36,6 +36,7 @@ #import #import #import +#import #import #import @@ -46,6 +47,8 @@ #import #import +#import + #import "UIxContactFolderActions.h" @implementation UIxContactFolderActions @@ -276,6 +279,7 @@ uid = [folder globallyUniqueObjectId]; [card setUid: uid]; + // TODO: shall we add .vcf as in [SOGoContactGCSEntry copyToFolder:] contact = [SOGoContactGCSEntry objectWithName: uid inContainer: folder]; [contact setIsNew: YES]; @@ -288,4 +292,33 @@ return rc; } +- (id ) saveAction +{ + SOGoContactGCSFolder *folder; + WORequest *request; + WOResponse *response; + NSDictionary *params, *message; + NSString *folderName; + + request = [context request]; + NSLog(@"%@", [request contentAsString]); + params = [[request contentAsString] objectFromJSONString]; + + folderName = [params objectForKey: @"name"]; + if ([folderName length] > 0) + { + folder = [self clientObject]; + [folder renameTo: folderName]; + response = [self responseWith204]; + } + else + { + message = [NSDictionary dictionaryWithObject: @"Missing name parameter" forKey: @"error"]; + response = [self responseWithStatus: 500 + andString: [message jsonRepresentation]]; + } + + return response; +} + @end /* UIxContactFolderActions */ diff --git a/UI/Contacts/UIxContactFoldersView.h b/UI/Contacts/UIxContactFoldersView.h index f300cc6e5..6bb658417 100644 --- a/UI/Contacts/UIxContactFoldersView.h +++ b/UI/Contacts/UIxContactFoldersView.h @@ -32,18 +32,18 @@ NSDictionary *currentContact; NSString *selectorComponentClass; NSMutableDictionary *moduleSettings; - id currentFolder; + //id currentFolder; BOOL contextIsSetup; } -- (NSArray *) contactFolders; +- (NSString *) contactFolders; - (NSArray *) personalContactInfos; -- (NSString *) currentContactFolderId; -- (NSString *) currentContactFolderOwner; -- (NSString *) currentContactFolderName; -- (NSString *) currentContactFolderClass; +// - (NSString *) currentContactFolderId; +// - (NSString *) currentContactFolderOwner; +// - (NSString *) currentContactFolderName; +// - (NSString *) currentContactFolderClass; - (WOResponse *) saveDragHandleStateAction; diff --git a/UI/Contacts/UIxContactFoldersView.m b/UI/Contacts/UIxContactFoldersView.m index aaf35d6c2..0550f14f7 100644 --- a/UI/Contacts/UIxContactFoldersView.m +++ b/UI/Contacts/UIxContactFoldersView.m @@ -22,6 +22,7 @@ #import #import #import +#import #import #import @@ -158,23 +159,88 @@ Class SOGoContactSourceFolderK, SOGoGCSFolderK; - (id ) allContactSearchAction { id result; - NSString *searchText; + SOGoFolder *folder; + NSString *searchText, *mail, *domain; NSDictionary *data; - NSArray *sortedContacts; - + NSArray *folders, *contacts, *descriptors, *sortedContacts; + NSMutableArray *sortedFolders; + NSMutableDictionary *contact, *uniqueContacts; + unsigned int i, j, max; + NSSortDescriptor *commonNameDescriptor; 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]; - - sortedContacts = [[self clientObject] allContactsFromFilter: searchText - excludeGroups: excludeGroups - excludeLists: excludeLists]; - - + 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]; data = [NSDictionary dictionaryWithObjectsAndKeys: searchText, @"searchText", sortedContacts, @"contacts", nil]; @@ -208,48 +274,72 @@ Class SOGoContactSourceFolderK, SOGoGCSFolderK; return [[self queryParameterForKey: @"popup"] boolValue]; } -- (NSArray *) contactFolders +- (NSString *) contactFolders { SOGoContactFolders *folderContainer; + NSArray *folders; + NSMutableArray *foldersAttrs; + NSDictionary *folderAttrs; + id currentFolder; + int max, i; folderContainer = [self clientObject]; - return [folderContainer subFolders]; + // return [folderContainer subFolders]; + + folders = [folderContainer subFolders]; + max = [folders count]; + foldersAttrs = [NSMutableArray arrayWithCapacity: max]; + for (i = 0; i < max; i++) + { + currentFolder = [folders objectAtIndex: i]; + folderAttrs = [NSDictionary dictionaryWithObjectsAndKeys: + [NSString stringWithFormat: @"%@", [currentFolder nameInContainer]], @"id", + [currentFolder displayName], @"name", + [currentFolder ownerInContext: context], @"owner", + [NSNumber numberWithBool: [currentFolder isKindOfClass: SOGoGCSFolderK]], @"isEditable", + [NSNumber numberWithBool: [currentFolder isKindOfClass: SOGoContactSourceFolderK] + && ![currentFolder isPersonalSource]], @"isRemote", + nil]; + [foldersAttrs addObject: folderAttrs]; + } + + return [foldersAttrs jsonRepresentation]; } -- (NSString *) currentContactFolderId -{ - return [NSString stringWithFormat: @"/%@", [currentFolder nameInContainer]]; -} +// - (NSString *) currentContactFolderId +// { +// return [NSString stringWithFormat: @"/%@", [currentFolder nameInContainer]]; +// } -- (NSString *) currentContactFolderName -{ - return [currentFolder displayName]; -} +// - (NSString *) currentContactFolderName +// { +// return [currentFolder displayName]; +// } -- (NSString *) currentContactFolderOwner -{ - return [currentFolder ownerInContext: context]; -} +// - (NSString *) currentContactFolderOwner +// { +// return [currentFolder ownerInContext: context]; +//} -- (NSString *) currentContactFolderClass -{ - return (([currentFolder isKindOfClass: SOGoContactSourceFolderK] - && ![currentFolder isPersonalSource]) - ? @"remote" : @"local"); -} +// - (NSString *) currentContactFolderClass +// { +// return (([currentFolder isKindOfClass: SOGoContactSourceFolderK] +// && ![currentFolder isPersonalSource]) +// ? @"remote" : @"local"); +// } -- (NSString *) currentContactFolderAclEditing -{ - return ([currentFolder isKindOfClass: SOGoGCSFolderK] - ? @"available": @"unavailable"); -} +// - (NSString *) currentContactFolderAclEditing +// { +// return ([currentFolder isKindOfClass: SOGoGCSFolderK] +// ? @"available": @"unavailable"); +// } -- (NSString *) currentContactFolderListEditing -{ - return ([currentFolder isKindOfClass: SOGoGCSFolderK] - ? @"available": @"unavailable"); -} +// - (NSString *) currentContactFolderListEditing +// { +// return ([currentFolder isKindOfClass: SOGoGCSFolderK] +// ? @"available": @"unavailable"); +//} - (NSString *) verticalDragHandleStyle { diff --git a/UI/Contacts/UIxContactView.h b/UI/Contacts/UIxContactView.h index 9f59c49b0..d5a9732c5 100644 --- a/UI/Contacts/UIxContactView.h +++ b/UI/Contacts/UIxContactView.h @@ -36,6 +36,8 @@ } - (NSString *) fullName; +- (NSArray *) orgUnits; +- (NSString *) photoURL; @end diff --git a/UI/Contacts/UIxContactView.m b/UI/Contacts/UIxContactView.m index 4a4541794..ea7ec03e4 100644 --- a/UI/Contacts/UIxContactView.m +++ b/UI/Contacts/UIxContactView.m @@ -21,6 +21,7 @@ */ #import +#import #import #import @@ -31,9 +32,13 @@ #import #import +#import +#import #import +#import #import #import +#import #import #import @@ -130,6 +135,45 @@ return [card fullName]; } +- (NSArray *) _languageContactsCategories +{ + NSArray *categoryLabels; + + categoryLabels = [[self labelForKey: @"contacts_category_labels"] componentsSeparatedByString: @","]; + if (!categoryLabels) + categoryLabels = [NSArray array]; + + return [categoryLabels trimmedComponents]; +} + +- (NSArray *) _fetchAndCombineCategoriesList +{ + NSString *ownerLogin; + SOGoUserDefaults *ud; + NSArray *cats, *newCats, *contactCategories; + + ownerLogin = [[self clientObject] ownerInContext: context]; + ud = [[SOGoUser userWithLogin: ownerLogin] userDefaults]; + cats = [ud contactsCategories]; + if (!cats) + cats = [self _languageContactsCategories]; + + contactCategories = [card categories]; + if (contactCategories) + { + newCats = [cats mergedArrayWithArray: contactCategories]; + if ([newCats count] != [cats count]) + { + cats = [newCats sortedArrayUsingSelector: + @selector (localizedCaseInsensitiveCompare:)]; + [ud setContactsCategories: cats]; + [ud synchronize]; + } + } + + return cats; +} + - (NSString *) primaryEmail { NSString *email, *fn, *attrs; @@ -236,14 +280,14 @@ return @""; } -- (NSString *) categories -{ - NSString *categories; +// - (NSString *) categories +// { +// NSString *categories; - categories = [[card categories] componentsJoinedByString: @", "]; - return [self _cardStringWithLabel: @"Categories:" - value: categories]; -} +// categories = [[card categories] componentsJoinedByString: @", "]; +// return [self _cardStringWithLabel: @"Categories:" +// value: categories]; +// } - (BOOL) hasTelephones { @@ -479,6 +523,101 @@ return [self _cardStringWithLabel: nil value: [card title]]; } +- (NSArray *) orgUnits +{ + NSMutableArray *orgUnits; + NSArray *values; + CardElement *org; + NSString *service; + NSUInteger count, max; + + org = [card org]; + values = [org valuesForKey: @""]; + max = [values count]; + if (max > 1) + { + orgUnits = [NSMutableArray arrayWithCapacity: max]; + for (count = 1; count < max; count++) + { + service = [org flattenedValueAtIndex: count forKey: @""]; + if ([service length] > 0) + [orgUnits addObject: [NSDictionary dictionaryWithObject: service forKey: @"value"]]; + } + } + else + orgUnits = nil; + + return orgUnits; +} + +- (NSArray *) categories +{ + NSMutableArray *categories; + NSArray *values; + NSString *category; + NSUInteger count, max; + + values = [card categories]; + max = [values count]; + if (max > 0) + { + categories = [NSMutableArray arrayWithCapacity: max]; + for (count = 0; count < max; count++) + { + category = [values objectAtIndex: count]; + if ([category length] > 0) + [categories addObject: [NSDictionary dictionaryWithObject: category forKey: @"value"]]; + } + } + else + categories = nil; + + return categories; +} + +- (NSArray *) deliveryAddresses +{ + NSMutableArray *addresses; + NSMutableDictionary *address; + NSArray *elements; + NSString *type, *postoffice, *street, *street2, *locality, *region, *postalcode, *country; + CardElement *adr; + NSUInteger count, max; + + elements = [card childrenWithTag: @"adr"]; + //values = [org valuesForKey: @""]; + max = [elements count]; + if (max > 0) + { + addresses = [NSMutableArray arrayWithCapacity: max]; + for (count = 1; count < max; count++) + { + adr = [elements objectAtIndex: count]; + type = [adr value: 0 ofAttribute: @"type"]; + postoffice = [adr flattenedValueAtIndex: 0 forKey: @""]; + street2 = [adr flattenedValueAtIndex: 1 forKey: @""]; + street = [adr flattenedValueAtIndex: 2 forKey: @""]; + locality = [adr flattenedValueAtIndex: 3 forKey: @""]; + region = [adr flattenedValueAtIndex: 4 forKey: @""]; + postalcode = [adr flattenedValueAtIndex: 5 forKey: @""]; + country = [adr flattenedValueAtIndex: 6 forKey: @""]; + address = [NSMutableDictionary dictionaryWithObject: type forKey: @"type"]; + if (postoffice) [address setObject: postoffice forKey: @"postoffice"]; + if (street2) [address setObject: street2 forKey: @"street2"]; + if (street) [address setObject: street forKey: @"street"]; + if (locality) [address setObject: locality forKey: @"locality"]; + if (region) [address setObject: region forKey: @"region"]; + if (postalcode) [address setObject: postalcode forKey: @"postalcode"]; + if (country) [address setObject: country forKey: @"country"]; + if ([[address allKeys] count] > 1) [addresses addObject: address]; + } + } + else + addresses = nil; + + return addresses; +} + - (NSString *) workService { NSMutableArray *orgServices; @@ -595,13 +734,14 @@ bday = [dateFormatter formattedDate: date]; } - return [self _cardStringWithLabel: @"Birthday:" value: bday]; + return bday; + //return [self _cardStringWithLabel: @"Birthday:" value: bday]; } -- (NSString *) tz -{ - return [self _cardStringWithLabel: @"Timezone:" value: [card tz]]; -} +// - (NSString *) tz +// { +// return [self _cardStringWithLabel: @"Timezone:" value: [card tz]]; +// } - (NSString *) note { @@ -617,11 +757,8 @@ withString: @"
"]; } - return [self _cardStringWithLabel: @"Note:" - value: note - byEscapingHTMLString: NO - asLinkScheme: nil - withLinkAttributes: nil]; + return note; + //return [self _cardStringWithLabel: @"Note:" value: note]; } /* hrefs */ @@ -669,6 +806,111 @@ return self; } +- (id ) dataAction +{ + id result; + id o; + SOGoObject *contact; + // NSMutableArray *description; + NSMutableDictionary *data; + + contact = [self clientObject]; + card = [contact vCard]; + if (card) + { + [card retain]; + phones = nil; + homeAdr = nil; + workAdr = nil; + NSLog(@"%@", [card versitString]); + } + else + return [NSException exceptionWithHTTPStatus: 404 /* Not Found */ + reason: @"could not locate contact"]; + + // description = [NSMutableArray array]; + data = [NSMutableDictionary dictionaryWithObjectsAndKeys: + [[contact container] nameInContainer], @"pid", + [contact nameInContainer], @"id", + [card tag], @"tag", + nil]; + o = [card fn]; + if (o) [data setObject: o forKey: @"fn"]; + o = [card n]; + if (o) + { + NSString *lastName = [o flattenedValueAtIndex: 0 forKey: @""]; + NSString *firstName = [o flattenedValueAtIndex: 1 forKey: @""]; + if ([lastName length] > 0) + [data setObject: lastName forKey: @"sn"]; + if ([firstName length] > 0) + [data setObject: firstName forKey: @"givenname"]; + } + o = [card nickname]; + if (o) [data setObject: o forKey: @"nickname"]; + // o = [card fullName]; + // if (o) [data setObject: o forKey: @"fullname"]; + o = [card title]; + if ([o length] > 0) + { + [data setObject: o forKey: @"title"]; + // [description addObject: o]; + } + o = [card role]; + if ([o length] > 0) + { + [data setObject: o forKey: @"role"]; + // [description addObject: o]; + } + o = [self orgUnits]; + if ([o count] > 0) + { + [data setObject: o forKey: @"orgUnits"]; + // [description addObjectsFromArray: o]; + } + o = [card workCompany]; + if ([o length] > 0) + { + [data setObject: o forKey: @"org"]; + // [description addObject: o]; + } + // if ([description count]) [data setObject: description forKey: @"description"]; + + o = [card birthday]; + if (o) + { + NSNumber *time = [NSNumber numberWithInt: [o timeIntervalSince1970]]; + [data setObject: time forKey: @"birthday"]; + } + // o = [card source]; + // if (o) [data setObject: o forKey: @"source"]; + o = [card tz]; + if (o) [data setObject: o forKey: @"tz"]; + + o = [card childrenWithTag: @"email"]; + if ([o count]) [data setObject: o forKey: @"emails"]; + o = [card childrenWithTag: @"tel"]; + if ([o count]) [data setObject: o forKey: @"phones"]; + o = [self categories]; + if ([o count]) [data setObject: o forKey: @"categories"]; + o = [self deliveryAddresses]; + if ([o count] > 0) [data setObject: o forKey: @"addresses"]; + o = [card childrenWithTag: @"url"]; + if ([o count]) [data setObject: o forKey: @"urls"]; + + o = [self note]; + if (o) [data setObject: o forKey: @"note"]; + o = [self _fetchAndCombineCategoriesList]; + if (o) [data setObject: o forKey: @"allCategories"]; + if ([contact hasPhoto]) + [data setObject: [self photoURL] forKey: @"photoURL"]; + + result = [self responseWithStatus: 200 + andString: [data jsonRepresentation]]; + + return result; +} + - (BOOL) hasPhoto { return [[self clientObject] hasPhoto]; diff --git a/UI/Contacts/UIxContactsListActions.m b/UI/Contacts/UIxContactsListActions.m index 7e631416e..b952f6da8 100644 --- a/UI/Contacts/UIxContactsListActions.m +++ b/UI/Contacts/UIxContactsListActions.m @@ -128,6 +128,7 @@ { id result; id currentInfo; + NSDictionary *data; NSArray *contactsList; NSEnumerator *contactsListEnumerator, *keysEnumerator; NSMutableArray *newContactsList; @@ -151,8 +152,13 @@ [newContactsList addObject: currentContactDictionary]; } + data = [NSDictionary dictionaryWithObjectsAndKeys: + [[self clientObject] nameInContainer], @"id", + newContactsList, @"contacts", + nil]; + result = [self responseWithStatus: 200 - andString: [newContactsList jsonRepresentation]]; + andString: [data jsonRepresentation]]; return result; } diff --git a/UI/Contacts/UIxListView.m b/UI/Contacts/UIxListView.m index 1e3547686..953b35ab2 100644 --- a/UI/Contacts/UIxListView.m +++ b/UI/Contacts/UIxListView.m @@ -1,8 +1,6 @@ /* UIxListView.m - this file is part of SOGo * - * Copyright (C) 2008-2009 Inverse inc. - * - * Author: Wolfgang Sourdeau + * Copyright (C) 2008-2014 Inverse inc. * * 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 @@ -27,6 +25,7 @@ #import #import +#import #import "UIxListView.h" @@ -141,6 +140,54 @@ return rc; } +- (id ) dataAction +{ + id result; + NSMutableDictionary *data; + NSMutableArray *cards; + NGVCardReference *card; + int i, count; + + co = [self clientObject]; + list = [co vList]; + + if (list) + { + [self checkListReferences]; + } + else + return [NSException exceptionWithHTTPStatus: 404 /* Not Found */ + reason: @"could not locate contact"]; + + count = [[list cardReferences] count]; + cards = [NSMutableArray arrayWithCapacity: count]; + for (i = 0; i < count; i++) + { + card = [[list cardReferences] objectAtIndex: i]; + [cards addObject: [NSDictionary dictionaryWithObjectsAndKeys: + [card reference], @"reference", + [card fn], @"fn", + [card email], @"email", + nil]]; + } + + data = [NSMutableDictionary dictionaryWithObjectsAndKeys: + [[co container] nameInContainer], @"pid", + [co nameInContainer], @"id", + [list tag], @"tag", + [list fn], @"fn", + [list description], @"description", + cards, @"refs", + nil]; + + // [list cardReferences] + + result = [self responseWithStatus: 200 + andString: [data jsonRepresentation]]; + + return result; +} + - (WOResponse *) propertiesAction { NSArray *references; diff --git a/UI/Contacts/product.plist b/UI/Contacts/product.plist index 7ed3b6314..32e48e3f9 100644 --- a/UI/Contacts/product.plist +++ b/UI/Contacts/product.plist @@ -74,6 +74,11 @@ actionClass = "UIxContactsListActions"; actionName = "contactsList"; }; + // contacts = { + // protectedBy = "View"; + // actionClass = "UIxContactsListActions"; + // actionName = "contactsList"; + // }; contactSearch = { protectedBy = ""; actionClass = "UIxContactsListActions"; @@ -109,6 +114,11 @@ actionClass = "UIxContactFolderActions"; actionName = "import"; }; + save = { + protectedBy = "Change Permissions"; + actionClass = "UIxContactFolderActions"; + actionName = "save"; + }; userRights = { protectedBy = "ReadAcls"; pageName = "UIxContactsUserRightsEditor"; @@ -171,6 +181,7 @@ view = { protectedBy = "Access Contents Information"; pageName = "UIxContactView"; + actionName = "data"; }; edit = { protectedBy = "Access Contents Information"; @@ -218,6 +229,7 @@ view = { protectedBy = "Access Contents Information"; pageName = "UIxListView"; + actionName = "data"; }; properties = { protectedBy = "Access Contents Information";