JSON-based operations on contacts

pull/91/head
Francis Lachapelle 2014-06-19 15:51:57 -04:00
parent 29e147ee86
commit 0a49031b01
13 changed files with 815 additions and 105 deletions

View File

@ -34,6 +34,9 @@
- (void) updateFromLDIFRecord: (NSDictionary *) ldifRecord;
- (NSMutableDictionary *) asLDIFRecord;
- (void) setAttributes: (NSDictionary *) attributes;
//- (NSDictionary *) attributes;
- (NSString *) workCompany;
- (NSString *) fullName;
- (NSArray *) secondaryEmails;

View File

@ -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;

View File

@ -84,6 +84,11 @@
return [self ldifRecord];
}
- (void) setAttributes: (NSDictionary *) newAttributes
{
[[self vCard] setAttributes: newAttributes];
}
- (BOOL) hasPhoto
{
return ([[self vCard] firstChildWithTag: @"photo"] != nil);

View File

@ -37,6 +37,8 @@
- (NSDictionary *) ldifRecord;
- (NSDictionary *) simplifiedLDIFRecord;
- (void) setAttributes: (NSDictionary *) newAttributes;
- (NSException *) save;
- (NSException *) delete;

View File

@ -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 <WOActionResults>) saveAction
{
SOGoObject <SOGoContactObject> *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

View File

@ -36,6 +36,7 @@
#import <Contacts/SOGoContactObject.h>
#import <Contacts/SOGoContactFolder.h>
#import <Contacts/SOGoContactFolders.h>
#import <Contacts/SOGoContactGCSFolder.h>
#import <Contacts/NSDictionary+LDIF.h>
#import <SoObjects/Contacts/NGVCard+SOGo.h>
@ -46,6 +47,8 @@
#import <SoObjects/Contacts/SOGoContactGCSFolder.h>
#import <GDLContentStore/GCSFolder.h>
#import <SOGo/NSString+Utilities.h>
#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 <WOActionResults>) 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 */

View File

@ -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;

View File

@ -22,6 +22,7 @@
#import <Foundation/NSDictionary.h>
#import <Foundation/NSEnumerator.h>
#import <Foundation/NSString.h>
#import <Foundation/NSValue.h>
#import <NGObjWeb/NSException+HTTP.h>
#import <NGObjWeb/SoObject.h>
@ -158,23 +159,88 @@ Class SOGoContactSourceFolderK, SOGoGCSFolderK;
- (id <WOActionResults>) allContactSearchAction
{
id <WOActionResults> result;
NSString *searchText;
SOGoFolder <SOGoContactFolder> *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
{

View File

@ -36,6 +36,8 @@
}
- (NSString *) fullName;
- (NSArray *) orgUnits;
- (NSString *) photoURL;
@end

View File

@ -21,6 +21,7 @@
*/
#import <Foundation/NSURL.h>
#import <Foundation/NSValue.h>
#import <NGObjWeb/NSException+HTTP.h>
#import <NGObjWeb/WOResponse.h>
@ -31,9 +32,13 @@
#import <NGExtensions/NSString+Ext.h>
#import <NGExtensions/NSString+misc.h>
#import <SOGo/CardElement+SOGo.h>
#import <SOGo/NSArray+Utilities.h>
#import <SOGo/NSCalendarDate+SOGo.h>
#import <SOGo/NSDictionary+Utilities.h>
#import <SOGo/SOGoDateFormatter.h>
#import <SOGo/SOGoUser.h>
#import <SOGo/SOGoUserDefaults.h>
#import <Contacts/NGVCard+SOGo.h>
#import <Contacts/SOGoContactObject.h>
@ -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: @"<br />"];
}
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 <WOActionResults>) dataAction
{
id <WOActionResults> result;
id o;
SOGoObject <SOGoContactObject> *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];

View File

@ -128,6 +128,7 @@
{
id <WOActionResults> 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;
}

View File

@ -1,8 +1,6 @@
/* UIxListView.m - this file is part of SOGo
*
* Copyright (C) 2008-2009 Inverse inc.
*
* Author: Wolfgang Sourdeau <wsourdeau@inverse.ca>
* 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 <NGCards/NGVCardReference.h>
#import <SOGo/NSArray+Utilities.h>
#import <SOGo/NSDictionary+Utilities.h>
#import "UIxListView.h"
@ -141,6 +140,54 @@
return rc;
}
- (id <WOActionResults>) dataAction
{
id <WOActionResults> 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;

View File

@ -74,6 +74,11 @@
actionClass = "UIxContactsListActions";
actionName = "contactsList";
};
// contacts = {
// protectedBy = "View";
// actionClass = "UIxContactsListActions";
// actionName = "contactsList";
// };
contactSearch = {
protectedBy = "<public>";
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";